创建cv::Mat时触发Segmentation Fault(malloc问题)求助
1. 容器未预先初始化,触发越界访问
mvImagePyramid 和 mvMaskPyramid 通常是 vector<cv::Mat> 类型,如果调用 ComputePyramid 前没有将它们的大小调整为 nlevels,直接通过 [level] 索引赋值会触发越界内存访问——这类错误不会每次都触发(取决于内存布局),但会随机引发malloc崩溃。
修复:
在类构造函数或调用 ComputePyramid 前,初始化容器大小:
mvImagePyramid.resize(nlevels); mvMaskPyramid.resize(nlevels);
2. 局部Mat的ROI引发内存冲突
你创建的 temp 是循环内的局部Mat,mvImagePyramid[level] = temp(Rect(...)) 让金字塔元素成为 temp 的ROI(共享内存)。后续调用 copyMakeBorder(image, temp, ...) 时,会直接修改 temp 的内存内容,若OpenCV在这个过程中触发内存重新分配(罕见的内存对齐问题),会导致之前的ROI引用指向无效内存,进而引发malloc错误。
修复:
调整代码顺序,先处理图像边框,再将有效区域关联到金字塔,避免依赖局部Mat的ROI:
for (int level = 0; level < nlevels; ++level) { float scale = mvInvScaleFactor[level]; Size sz(cvRound((float)image.cols*scale), cvRound((float)image.rows*scale)); Size wholeSize(sz.width + EDGE_THRESHOLD*2, sz.height + EDGE_THRESHOLD*2); if (!Mask.empty()) { cv::Mat resized_mask(sz, Mask.type()); resize(Mask, resized_mask, sz, 0, 0, INTER_NEAREST); resized_mask.copyTo(mvMaskPyramid[level]); } // 先创建带边框的临时图像,再提取ROI到金字塔 cv::Mat temp(wholeSize, image.type()); if( level != 0 ) { resize(mvImagePyramid[level-1], mvImagePyramid[level], sz, 0, 0, INTER_LINEAR); copyMakeBorder(mvImagePyramid[level], temp, EDGE_THRESHOLD, EDGE_THRESHOLD, EDGE_THRESHOLD, EDGE_THRESHOLD, BORDER_REFLECT_101+BORDER_ISOLATED); } else { copyMakeBorder(image, temp, EDGE_THRESHOLD, EDGE_THRESHOLD, EDGE_THRESHOLD, EDGE_THRESHOLD, BORDER_REFLECT_101); mvImagePyramid[level] = temp(Rect(EDGE_THRESHOLD, EDGE_THRESHOLD, sz.width, sz.height)); } }
3. 传值参数导致内存碎片化
函数参数 cv::Mat image 和 cv::Mat Mask 采用传值方式,每次调用都会创建图像副本,频繁调用会导致内存碎片化,偶发malloc分配失败。
修复:
改成传引用,避免不必要的拷贝:
void ORBextractor::ComputePyramid(const cv::Mat& image, const cv::Mat& Mask) { // ... 原有代码逻辑不变 }
4. 边界计算的潜在溢出
如果 nlevels 过大,scale = mvInvScaleFactor[level] 可能过小,导致 sz.width 或 sz.height 计算为0,后续创建0尺寸的Mat可能触发OpenCV内部内存分配异常(偶发)。
检查点:
添加断言验证尺寸合法性,调试时快速定位问题:
float scale = mvInvScaleFactor[level]; Size sz(cvRound((float)image.cols*scale), cvRound((float)image.rows*scale)); CV_Assert(sz.width > 0 && sz.height > 0);
内容的提问来源于stack exchange,提问作者Mort Smith

