-3

I can't get my head around this error. I'm working on a project using opencv trying to use hog and svm, inspired by this example: https://docs.opencv.org/3.4.1/d5/d77/train_HOG_8cpp-example.html#_a33 (the code is really similar). The error is in the second line of this function on imgs[0]. I understood that the error is there because I tried to print the entire image with cout << imgs[0]; and it doesn't print the entire matrix but the error appears at a certain point.

void computeHOG(const vector<Mat> &imgs, vector<Mat> &gradients) {
  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 r = Rect((imgs[i].rows - hog.winSize.height) / 2,
                    (imgs[i].cols - hog.winSize.width) / 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());
    }
  }
}

This is my Makefile

LDIR=lib
ODIR=build

CXX=g++
CXXFLAGS= -std=c++11 -Wall -Wextra -fsanitize=address -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
    $(CXX) -c -o $@ $< $(CXXFLAGS)

$(ODIR)/%.o: main.cpp $(DEPS)
    $(CXX) -c -o $@ $< $(CXXFLAGS)

main: $(OBJ)
    $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)

clean:
    rm -f $(ODIR)/*.o

.PHONY: clean

It compiles but when I run it I get:

ASAN:SIGSEGV
=================================================================
==670==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000040 (pc 0x00000040c917 bp 0x7ffe8906f990 sp 0x7ffe8906f980 T0)
    #0 0x40c916 in cv::MatSize::operator()() const (/[...]/opencv-project/main+0x40c916)
    #1 0x40ada0 in computeHOG(std::vector<cv::Mat, std::allocator<cv::Mat> > const&, std::vector<cv::Mat, std::allocator<cv::Mat> >&) (/[...]/opencv-project/main+0x40ada0)
    #2 0x4030df in main (/[...]/opencv-project/main+0x4030df)
    #3 0x7f511da2082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #4 0x402b48 in _start (/[...]/opencv-project/main+0x402b48)

AddressSanitizer can not provide additional info. SUMMARY: AddressSanitizer: SEGV ??:0 cv::MatSize::operator()() const
==670==ABORTING

If I remove -fsanitize=address from the Makefile,the error comes from compiling, is really too big to paste here but starts with something like this

main.cpp:(.text+0x20): undefined reference to `__asan_option_detect_stack_use_after_return'
main.cpp:(.text+0x30): undefined reference to `__asan_stack_malloc_4'
build/main.o: In function `__static_initialization_and_destruction_0(int, int)':
main.cpp:(.text+0x970): undefined reference to `__asan_before_dynamic_init'
main.cpp:(.text+0x9d4): undefined reference to `__asan_report_load1'
main.cpp:(.text+0xa14): undefined reference to `__asan_report_store1'
main.cpp:(.text+0xa64): undefined reference to `__asan_report_load1'

My g++ version is g++ (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609 Didn't find any solution looking for it...

  • `imgs[0].size()` is Undefined Behavior if `imgs` is ever empty. – Drew Dormann May 23 '18 at 22:12
  • Compile with `-g -fno-omit-frame-pointer` and ASAN will give you more information. https://clang.llvm.org/docs/AddressSanitizer.html – Justin May 23 '18 at 22:12
  • @DrewDormann I wrote that I printed almost the entire matrix... –  May 24 '18 at 07:05
  • @Justin with those flags I have the same error. Notice that `AddressSanitizer can not provide additional info.` –  May 24 '18 at 07:06
  • @Justin `-fno-omit-frame-pointer` is only needed to get locations of heap allocations so it won't help here. Clang documentation should have been more explicit on this. – yugr May 24 '18 at 08:17
  • @DrewDormann True but even then it probly won't be able to cause SEGV in `operator ()`. – yugr May 24 '18 at 08:17

1 Answers1

1

Your code accesses NULL pointer at some point when calling Mat::operator (). Reasons for this are unclear from the snippet you've posted but should be obvious if you run your code from debugger.

Undefined references when removing -fsanitize=address suggests that some code wasn't recompiled after you changed Makefile. Can you first do make clean?

As a side note, you should append -fsanitize=address to your LDFLAGS as well (to link in runtime library).

yugr
  • 19,769
  • 3
  • 51
  • 96