Using MOG2_GPU (from opencv) leads to "pure virtual method called" on exit.

I’ve attached an ofx project that shows the problem, and leads to the following stack-trace when exiting:

pure virtual method called
terminate called without an active exception

[pre]Program received signal SIGABRT, Aborted.
0x00007fffc5c07425 in __GI_raise (sig=) at …/nptl/sysdeps/unix/sysv/linux/raise.c:64
64 …/nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 0x00007fffc5c07425 in __GI_raise (sig=) at …/nptl/sysdeps/unix/sysv/linux/raise.c:64
#1 0x00007fffc5c0ab8b in __GI_abort () at abort.c:91
#2 0x00007fffc655969d in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007fffc6557846 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007fffc6557873 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007fffc655828f in __cxa_pure_virtual () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x00007fffc8a3656f in cv::gpu::GpuMat::release() () from /usr/local/lib/libopencv_core.so.2.4
#7 0x00000000004144c1 in ~GpuMat (this=0xae8218, __in_chrg=)
at /usr/local/include/opencv2/core/gpumat.hpp:374
#8 testApp::~testApp (this=0xae8070, __in_chrg=) at src/testApp.h:10
#9 0x0000000000414573 in testApp::~testApp (this=0xae8070, __in_chrg=) at src/testApp.h:10
#10 0x00000000004429e9 in ofPtr::~ofPtr() ()
#11 0x00007fffc5c0c901 in __run_exit_handlers (status=0, listp=0x7fffc5f89688, run_list_atexit=true) at exit.c:78
#12 0x00007fffc5c0c985 in __GI_exit (status=) at exit.c:100
#13 0x00000000004f67c8 in exitApp() ()
#14 0x00000000004f8d36 in ofNotifyKeyPressed(int) ()
#15 0x00007fffc6f72a7f in glutMainLoopEvent () from /usr/lib/x86_64-linux-gnu/libglut.so.3
#16 0x00007fffc6f72f05 in glutMainLoop () from /usr/lib/x86_64-linux-gnu/libglut.so.3
#17 0x00000000004426e0 in ofRunApp(ofBaseApp*) ()
#18 0x0000000000412493 in main () at src/main.cpp:9[/pre]

This seems to only happen in ofx, if I use the same calls in a pure opencv program (as follows) the exit is clean:

[pre]#include
#include

#include “opencv2/opencv_modules.hpp”
#include “opencv2/core/core.hpp”
#include “opencv2/gpu/gpu.hpp”
#include “opencv2/highgui/highgui.hpp”

int main(int argc, const char** argv)
{

cv::gpu::MOG2_GPU MOG2model;
cv::gpu::GpuMat tmpGPUout, GPUframe, GPUbackground;
cv::Mat image;

MOG2model.bShadowDetection = false;
cv::Mat testImage = cv::imread(“test.jpg”);
GPUframe.upload(testImage);

namedWindow(“image”, cv::WINDOW_NORMAL);

for(;:wink:
{
MOG2model(GPUframe,tmpGPUout);
MOG2model.getBackgroundImage(GPUbackground);
GPUframe.download(image);
cv::imshow(“image”, image);

int key = cv::waitKey(30);
if (key == 27)
break;
}

return 0;
}[/pre]

I’m not even really sure what this error means, but seems related to the destruction of the GPUMats. I have no idea where to go from here to resolve this.

The attachment includes my custom make config for opencv_gpu, edit as needed.

Thank you.

emptyExample-debugPureVirtual.tgz

Just taking a guess here, but I think that’s the destructor called on the GPU::Mat. Looking at the docs I see:

You are not recommended to leave static or global GpuMat variables allocated, that is, to rely on its destructor. The destruction order of such variables and CUDA context is undefined. GPU memory release function returns error if the CUDA context has been destroyed before.

Here: http://docs.opencv.org/trunk/modules/gpu/doc/data-structures.html#gpu-gpumat

That doesn’t quite match what you’re seeing, but it does indicate that the memory destruction on the GPU is a little different than on the CPU, so I think it might just be OF not destroying memory correctly?

Thanks Joshua,

Yes, there are GpuMats in the MOG class, but those should be cleaned up on destruction. Ok, there does not seem to be a destructor for MOG2_GPU (https://github.com/Itseez/opencv/blob/c92954716472c53596337af7299874099e529039/modules/gpubgsegm/src/mog.cpp) so we need to call release() for MOG2_GPU, but that is what I do in the code in which I originally saw the problem and it made no difference.

I just did a quick test, and putting explicit release() calls in my example code, and the error persists…

emptyExample-debugPureVirtual-2.tgz