Yalantis/uCrop · warning

assign(): Shared image instance has overlapping memory.

Error message

assign(): Shared image instance has overlapping memory.

What it means

CImg<T>::assign(values,...) for a shared image (is_shared=true) makes the instance wrap external memory without copying. It only warns (non-fatal) when the caller-provided buffer partially overlaps the instance's own existing buffer, i.e. values+siz falls inside [_data, _data+size) without being fully disjoint; such aliasing makes future reads/writes ill-defined because two logical images share bytes with offset skew.

Source

Thrown at ucrop/src/main/jni/CImg.h:13725

      if (is_shared)
        throw CImgArgumentException(_cimg_instance
                                    "assign(): Invalid assignment request of shared instance from (%s*) buffer "
                                    "(pixel types are different).",
                                    cimg_instance,
                                    CImg<t>::pixel_type());
      return assign(values,size_x,size_y,size_z,size_c);
    }

    //! Construct image with specified size and initialize pixel values from a memory buffer \overloading.
    CImg<T>& assign(const T *const values, const unsigned int size_x, const unsigned int size_y,
                    const unsigned int size_z, const unsigned int size_c, const bool is_shared) {
      const size_t siz = safe_size(size_x,size_y,size_z,size_c);
      if (!values || !siz) return assign();
      if (!is_shared) { if (_is_shared) assign(); assign(values,size_x,size_y,size_z,size_c); }
      else {
        if (!_is_shared) {
          if (values + siz<_data || values>=_data + size()) assign();
          else cimg::warn(_cimg_instance
                          "assign(): Shared image instance has overlapping memory.",
                          cimg_instance);
        }
        _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; _is_shared = true;
        _data = const_cast<T*>(values);
      }
      return *this;
    }

    //! Construct image from memory buffer with specified size and pixel ordering scheme.
    template<typename t>
    CImg<T>& assign(const t *const values, const unsigned int size_x, const unsigned int size_y,
                    const unsigned int size_z, const unsigned int size_c,
                    const char *const axes_order) {
      CImg<T>(values,size_x,size_y,size_z,size_c,axes_order).move_to(*this);
    }

    //! Construct image from reading an image file \inplace.

View on GitHub (pinned to f788b534b4)

Solutions

  1. Ensure the shared buffer is either fully disjoint from the instance's current buffer or exactly coincides with it
  2. Copy the overlapping region to fresh memory and assign from the copy
  3. Assign the unshared instance first (assign(values,...) with is_shared=false) so the data is duplicated
  4. Re-check pointer arithmetic: if wrapping a sub-region is intended, use get_crop()/get_shared_crop() instead of raw assign()

Example fix

// before
img.assign(img.data() + 10, w, h, 1, 1, true); // partial overlap with own buffer
// after
CImg<T> sub = img.get_crop(10, 0, 0, 0, 10 + w - 1, h - 1, 0, 0); // proper sub-image copy
Defensive patterns

Strategy: type-guard

Validate before calling

bool disjoint(const T* values, size_t siz, const CImg<T>& img) {
  return values + siz < img.data() || values >= img.data() + img.size();
}
if (disjoint(values, siz, img)) img.assign(values, w, h, d, s, true);

Type guard

template <typename T>
bool no_overlap(const T* buf, size_t n, const CImg<T>& img) {
  const T* b = img.data();
  return !img.size() || !n || buf + n <= b || buf >= b + img.size();
}

Prevention

When it happens

Trigger: Calling assign(values,size_x,size_y,size_z,size_c) with is_shared=true where `values` points inside the current image's own _data buffer but not exactly at its start or covering it exactly (partial overlap).

Common situations: Reshaping a shared image in-place from a sub-window of its own buffer, cropping code that passes a pointer computed from the same image, reusing stale pointers after a previous assign changed _data.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08). Data as JSON: /api/errors/2ae1e5d2e7683a76. Report an issue: GitHub.