OpenCV HOG/SVM项目遇AddressSanitizer段错误及编译问题求助
问题分析与解决方案
我来帮你一步步解决这两个问题——首先是HOG计算时的段错误,然后是移除AddressSanitizer后的编译错误。
1. 解决AddressSanitizer触发的SEGV段错误
你的错误直接发生在imgs[0].size()这一行,这说明传入computeHOG的imgs向量是空的,或者imgs[0]是一个无效的、悬空的或未初始化的Mat对象。
具体修复步骤:
- 先给
computeHOG加上输入有效性检查,从源头避免非法访问:void computeHOG(const vector<Mat> &imgs, vector<Mat> &gradients) { // 先检查输入向量是否为空 if (imgs.empty()) { cerr << "Error: Input image vector is empty!" << endl; return; } // 检查第一个图像是否有效(未损坏、已正确加载) if (imgs[0].empty() || !imgs[0].data) { cerr << "Error: First image in the vector is invalid!" << endl; return; } HOGDescriptor hog; hog.winSize = imgs[0].size() / 8 * 8; vector<float> descriptors; Mat gray; for (size_t i = 0; i < imgs.size(); ++i) { if (imgs[i].rows >= hog.winSize.height && imgs[i].cols >= hog.winSize.width) { // 注意:Rect的参数顺序是(x, y, width, height),你之前写反了行和列的偏移! Rect r = Rect((imgs[i].cols - hog.winSize.width)/2, (imgs[i].rows - hog.winSize.height)/2, hog.winSize.width, hog.winSize.height); cvtColor(imgs[i](r), gray, COLOR_BGR2GRAY); hog.compute(gray, descriptors, Size(8, 8), Size(0, 0)); gradients.push_back(Mat(descriptors).t()); } } } - 检查调用
computeHOG的代码,确认传入的imgs已经正确加载了图像:比如用imread读取文件时,要检查返回的Mat是否为空(避免路径错误、文件损坏的情况)。 - 额外提醒:你之前的
Rect构造参数顺序错误,把行偏移和列偏移写反了,这个错误虽然不是当前段错误的直接原因,但后续裁剪图像时会触发越界访问,必须修正。
2. 解决移除-fsanitize=address后的未定义引用错误
这个问题的核心是你的Makefile存在编译规则错误,且新旧编译产物冲突:
修复Makefile:
- 你的Makefile里
$(ODIR)/%.o: main.cpp $(DEPS)这条规则是错误的,它会让所有.o文件(包括io.o、hog.o)都用main.cpp编译,这会导致大量符号混乱。改成针对main.o的单独规则:LDIR=lib ODIR=build CXX=g++ CXXFLAGS= -std=c++11 -Wall -Wextra -I$(LDIR) LIBS=-lopencv_calib3d -lopencv_core -lopencv_features2d -lopencv_flann -lopencv_highgui -lopencv_imgcodecs -lopencv_imgproc -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_shape -lopencv_stitching -lopencv_superres -lopencv_video -lopencv_videoio _DEPS=io.hpp hog.hpp DEPS=$(patsubst %,$(LDIR)/%,$(_DEPS)) _OBJ=main.o io.o hog.o OBJ=$(patsubst %,$(ODIR)/%,$(_OBJ)) $(ODIR)/%.o: $(LDIR)/%.cpp $(DEPS) $(CXX) -c -o $@ $< $(CXXFLAGS) $(ODIR)/main.o: main.cpp $(DEPS) $(CXX) -c -o $@ $< $(CXXFLAGS) main: $(OBJ) $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS) clean: rm -f $(ODIR)/*.o .PHONY: clean - 移除
-fsanitize=address后,必须先清理之前用ASAN编译生成的旧目标文件,再重新编译:make clean && make
额外调试建议
- 在调用
computeHOG之前,打印输入向量的基本信息,确认数据有效性:cout << "Total images loaded: " << imgs.size() << endl; if (!imgs.empty()) { cout << "First image dimensions: " << imgs[0].rows << "x" << imgs[0].cols << endl; } - 你的g版本5.4.0比较老旧,如果后续遇到更多ASAN相关的兼容性问题,可以考虑升级到g7.x及以上版本,但当前问题通过上述修复即可解决。
内容的提问来源于stack exchange,提问作者user7891436
相关产品推荐
相关产品推荐

