2011-12-21 5 views
5

Mam przeciek pamięci w mojej aplikacji OpenCV. Jest to aplikacja średniej wielkości z dozonem klas i kilkoma tysiącami linii kodu. W jakiś sposób udało mi się wytworzyć duży wyciek pamięci w mojej aplikacji, który pochłania całą moją pamięć 8GB w ciągu kilku minut. Używam OpenCV C++ 2.3 na Ubuntu 11.10 z CMake.W aplikacji OpenCV jak zidentyfikować źródło wycieku pamięci i naprawić?

An snapshot of how much memory is freed right after I terminate the app. I can watch the used memory go up to 4gig in a matter of a few minutes

Jest aplikacji śledzenia ręcznie i przetwarzanie dwóch strumieni wideo jednoczesnej są z prędkością od około 15 klatek dla każdej kamery.

Próbowałem używać valgrind jak poniżej, ale wynik valgrind jest tak duży, że przekracza ilość tekstu, jaką można zachować w buforze. Wiem, że mogę zapisać dane wyjściowe do pliku dziennika, ale miałem nadzieję uniknąć trudnego zadania przeczytania tego wszystkiego. Oto komenda valgrind użyłem:

valgrind --tool=memcheck --leak-check=full --show-reachable=yes ./Gibbon 

Oto kilka ostatnich wierszy wyjścia valgrind:

==3573== 5,415,576 (1,176 direct, 5,414,400 indirect) bytes in 7 blocks are definitely lost in loss record 2,571 of 2,571 
==3573== at 0x4C28F9F: malloc (vg_replace_malloc.c:236) 
==3573== by 0x5B2ACD0: cv::fastMalloc(unsigned long) (in /usr/local/lib/libopencv_core.so.2.3.1) 
==3573== by 0x5A7FA9D: cvCreateImageHeader (in /usr/local/lib/libopencv_core.so.2.3.1) 
==3573== by 0x484538: CameraPGR::convertImageToOpenCV(FlyCapture2::Image*) (CameraPGR.cpp:212) 
==3573== by 0x483F52: CameraPGR::grabImage() (CameraPGR.cpp:134) 
==3573== by 0x473F86: start() (GibbonMain.cpp:368) 
==3573== by 0x4725CC: main (GibbonMain.cpp:108) 
==3573== 
==3573== LEAK SUMMARY: 
==3573== definitely lost: 24,432 bytes in 33 blocks 
==3573== indirectly lost: 5,414,640 bytes in 15 blocks 
==3573==  possibly lost: 2,314,837 bytes in 1,148 blocks 
==3573== still reachable: 496,811 bytes in 4,037 blocks 
==3573==   suppressed: 0 bytes in 0 blocks 
==3573== 
==3573== For counts of detected and suppressed errors, rerun with: -v 
==3573== Use --track-origins=yes to see where uninitialised values come from 
==3573== ERROR SUMMARY: 336 errors from 318 contexts (suppressed: 10 from 8) 

Jakie są lepsze sposoby, że mogę podchodzić do tego problemu? Czy są jakieś narzędzia, które mogą pokazać mi w zwięzły sposób, jakie wywołania funkcji powodują większość przydziałów pamięci? Jeśli valgrind jest odpowiedzią, doceniłbym kilka wskazówek, jak używać go w bardziej efektywny sposób, ponieważ jestem całkowicie nowy w tym narzędziu.

+0

Gdybym musiał zgadnąć, powiedziałbym, że prawdopodobnie przydzielasz pamięć gdzieś w okolicy 'CameraPGR :: grabImage()' i nigdy go nie zwalniasz. –

+0

Spojrzałem na tę funkcję kilka razy, nie mogę znaleźć problemu. Zrobię z tym jutro trochę więcej zamieszania. Czy masz jakieś sugestie, w jaki sposób mogę poprawić proces znajdowania głównej przyczyny wycieku pamięci? – Aras

+1

Nie widząc żadnego kodu, niemożliwe jest odgadnięcie, co się dzieje. Czy zwolnisz pamięć przydzieloną w powyższym stanie? Jeśli nie, masz problem. –

Odpowiedz

5

Brak odpowiedzi, ale sugestia: Przejdź z interfejsu OpenCV C do C++. Jeśli zostanie właściwie wykorzystany, zminimalizuje szanse na wyciek, teraz iw przyszłości. Inteligentne wskaźniki wbudowane w obiekty automatycznie zwalniają pamięć.

W najgorszym przypadku będziesz mieć karę za wydajność (zbyt wiele allocs/deallocs), ale są one łatwe do wykrycia w profilerze.

interfejs C++ używa

Mat intead of IplImage, 
Point instead of CvPoint, 
cv::function() instead of cvFunction. 

I nie trzeba zadeklarować wskaźniki do obrazów:

Mat src = imread("myfile.jpg"); 
Mat gray; // note that I do not allocate it. 
// This is done automatically in the next functions 
cv::cvtColor(src, gray, CV_BGR2GRAY); 
imshow("Gray image", gray); 
waitKey(); 

Jeśli masz trochę starszych kod, lub przez stronę trzecią, która używa drugiego interfejs, łatwo przekonwertować iz powrotem:

Mat src(width, height, CV_8UC3); 
IplImage* legacyImg; 
legacyImg = &(IplImage)src; 

Inne typy danych (jak CvPoint) są automatycznie konwertowane. CvSeq zostaje zastąpione przez std::vector<T>

+0

Dzięki za sugestię.Poza tym, że czytałem obraz z kamery, o którym pisałem jakiś rok temu, nie używam interfejsu C nigdzie indziej. Odkąd odkryłem interfejs C++, używam go ciągle. Ale i tak dzięki! – Aras