{"record":{"id":"2ae1e5d2e7683a76","repo":"Yalantis/uCrop","slug":"assign-shared-image-instance-has-overlapping-me","errorCode":null,"errorMessage":"assign(): Shared image instance has overlapping memory.","messagePattern":"assign\\(\\): Shared image instance has overlapping memory\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"ucrop/src/main/jni/CImg.h","lineNumber":13725,"sourceCode":"      if (is_shared)\n        throw CImgArgumentException(_cimg_instance\n                                    \"assign(): Invalid assignment request of shared instance from (%s*) buffer \"\n                                    \"(pixel types are different).\",\n                                    cimg_instance,\n                                    CImg<t>::pixel_type());\n      return assign(values,size_x,size_y,size_z,size_c);\n    }\n\n    //! Construct image with specified size and initialize pixel values from a memory buffer \\overloading.\n    CImg<T>& assign(const T *const values, const unsigned int size_x, const unsigned int size_y,\n                    const unsigned int size_z, const unsigned int size_c, const bool is_shared) {\n      const size_t siz = safe_size(size_x,size_y,size_z,size_c);\n      if (!values || !siz) return assign();\n      if (!is_shared) { if (_is_shared) assign(); assign(values,size_x,size_y,size_z,size_c); }\n      else {\n        if (!_is_shared) {\n          if (values + siz<_data || values>=_data + size()) assign();\n          else cimg::warn(_cimg_instance\n                          \"assign(): Shared image instance has overlapping memory.\",\n                          cimg_instance);\n        }\n        _width = size_x; _height = size_y; _depth = size_z; _spectrum = size_c; _is_shared = true;\n        _data = const_cast<T*>(values);\n      }\n      return *this;\n    }\n\n    //! Construct image from memory buffer with specified size and pixel ordering scheme.\n    template<typename t>\n    CImg<T>& assign(const t *const values, const unsigned int size_x, const unsigned int size_y,\n                    const unsigned int size_z, const unsigned int size_c,\n                    const char *const axes_order) {\n      CImg<T>(values,size_x,size_y,size_z,size_c,axes_order).move_to(*this);\n    }\n\n    //! Construct image from reading an image file \\inplace.","sourceCodeStart":13707,"sourceCodeEnd":13743,"githubUrl":"https://github.com/Yalantis/uCrop/blob/f788b534b48c144edf786c8cddbf0e029e637804/ucrop/src/main/jni/CImg.h#L13707-L13743","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Ensure the shared buffer is either fully disjoint from the instance's current buffer or exactly coincides with it","Copy the overlapping region to fresh memory and assign from the copy","Assign the unshared instance first (assign(values,...) with is_shared=false) so the data is duplicated","Re-check pointer arithmetic: if wrapping a sub-region is intended, use get_crop()/get_shared_crop() instead of raw assign()"],"exampleFix":"// before\nimg.assign(img.data() + 10, w, h, 1, 1, true); // partial overlap with own buffer\n// after\nCImg<T> sub = img.get_crop(10, 0, 0, 0, 10 + w - 1, h - 1, 0, 0); // proper sub-image copy","handlingStrategy":"type-guard","validationCode":"bool disjoint(const T* values, size_t siz, const CImg<T>& img) {\n  return values + siz < img.data() || values >= img.data() + img.size();\n}\nif (disjoint(values, siz, img)) img.assign(values, w, h, d, s, true);","typeGuard":"template <typename T>\nbool no_overlap(const T* buf, size_t n, const CImg<T>& img) {\n  const T* b = img.data();\n  return !img.size() || !n || buf + n <= b || buf >= b + img.size();\n}","tryCatchPattern":null,"preventionTips":["Never assign a shared view from a pointer inside the image's own buffer","Use get_crop()/get_shared_crop() for sub-region views","Copy overlapping regions to fresh memory first","Document ownership of shared buffers to avoid stale-pointer reuse"],"tags":["memory","aliasing","shared-image","buffer-overlap","cimg"],"backgroundTag":"invalid-argument-value","analyzedSha":"f788b534b48c144edf786c8cddbf0e029e637804","analyzedAt":"2026-09-08T08:36:04.887Z","contentChangedAt":"2026-09-08T08:36:04.887Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}