2015-05-08 4 views
1

У меня есть простой код, написанный в Visual Studio 2010 с openCV 2.4.10, который извлекает некоторые функции из некоторого входного файла.Обнаружение кучи OpenCV в режиме освобождения

Mat extractSIFT(Mat img) 
{ 
    cv::Ptr<cv::FeatureDetector> detector; 
    cv::Ptr<cv::Feature2D> descriptorExtractor; 

    detector = cv::FeatureDetector::create("Dense"); 
    descriptorExtractor = cv::DescriptorExtractor::create("SIFT"); 

    detector->set("initXyStep",GRID_SPACING); 

    vector<cv::KeyPoint> keypoints; 
    detector->detect(img,keypoints); 

    Mat o; 
    //Mat o(keypoints.size(),128,CV_8U); 
    descriptorExtractor->compute(img,keypoints,o); 

    return o; 
} 

Хотя этот код хорошо в режиме отладки (хотя и медленно) работает, он дает эту ошибку:

Windows has triggered a breakpoint in Prototype.exe.

This may be due to a corruption of the heap, which indicates a bug in Prototype.exe or any of the DLLs it has loaded.

This may also be due to the user pressing F12 while Prototype.exe has focus.

The output window may have more diagnostic information.

При дальнейшем расследовании, я обнаружил, что выходная переменная о не может рассматриваться в режиме выпуска (наведите указатель мыши), но может печатать значения на простом дампе консоли.

В дизассемблере:

848:  //Mat o(keypoints.size(),128,CV_8U); 
    849:  descriptorExtractor->compute(img,keypoints,o); 
    850: 
    851:  return o; 
013F6FCF 56     push  esi 
013F6FD0 8D 55 C0    lea   edx,[keypoints] 
013F6FD3 52     push  edx 
013F6FD4 8D 45 0C    lea   eax,[img] 
013F6FD7 50     push  eax 
013F6FD8 8B CF    mov   ecx,edi 
013F6FDA C7 45 F0 01 00 00 00 mov   dword ptr [ebp-10h],1 
013F6FE1 E8 42 35 02 00  call  cv::Feature2D::compute (141A528h) 
013F6FE6 8B 45 C0    mov   eax,dword ptr [keypoints] 
013F6FE9 3B C3    cmp   eax,ebx 
013F6FEB 74 09    je   extractSIFT4+306h (13F6FF6h) 
013F6FED 50     push  eax 
**013F6FEE E8 EC 5C 02 00  call  operator delete (141CCDFh)** 
013F6FF3 83 C4 04    add   esp,4 

Ошибка возникает в соответствии с звездочками. Я попробовал несколько свойств проекта (/ Md, MT, инкрементная сборка, ...) перекомпилировал openCV, проверенную версию платформы (v100), но безрезультатно.

+0

, какие библиотеки вы Кинк против? – Micka

+2

Kink? Что такое перегиб? Эта часть кода использует только opencv и dirent для списка папок – AutomaticHourglass

+0

^^ link, ofc ... – berak

ответ

3

Для получения разводов кучи любого рода Microsoft Application Verifier (freeware) бесценен. Вам нужно будет настроить его с помощью проверки Basics \ Heaps, я предлагаю отключить все другие проверки в первый раз. После сохранения настроек вам необходимо перезапустить программу. Он будет разбиваться точно в момент коррупции.

Например: предположим, что вы распределяете 100 байтов в кучу, а затем пытаетесь записать 101 байт. В сборках Debug C++ CRT добавит дополнительное дополнение до и после блока, что предотвратит и обнаружит небольшое кучевое повреждение. В сборках выпусков нет отступов, а куча повреждена, что вы обычно узнаете слишком поздно, в момент какой-либо другой операции кучи. С помощью Application Verifier ваша программа будет сбой в отладчике именно тогда, когда он пишет 101-й байт. Когда это произойдет, вы можете увидеть некоторые дополнительные детали в окне вывода Visual Studio.

(NB: Я всегда Application Verifier с Basics \ куч включена для программ я разрабатываю)

В данном конкретном случае, возможно, вы увидите, деструктор этого вектора приводит к аварии. Это будет означать, что не произошло кучи, но программа пытается удалить несуществующий блок кучи. Скорее всего, это связано с привязкой OpenCV, скомпилированным с другим компилятором или различными настройками Debug/Release. структура класса vector и выделенные блокировки блоков различаются между компиляторами и Debug/Release.

Обновление: Теперь, когда мы знаем, что другой CRT - это случай, вот расширенное объяснение.

  • вектор выделен OpenCV и свободен в вашей программе.
  • , если у вас есть разные версии CRT (компилятор, отладки/релиз)
    • выделение и освобождение логики может быть совершенно разными
    • вашей программа, скорее всего, авария.
  • если у вас есть та же версия CRT
    • CRT (C Runtime библиотеки) обрабатывает выделение памяти через Windows, кучи.
    • Каждая куча имеет свою ручку.
    • CRT (до VS2012 или что-то подобное) создаст собственную кучу для распределения.
    • Если у вас есть два разных ЭЛТ, тогда попытка освободить блок, выделенный другим CRT, будет использовать неправильный дескриптор кучи, который приведет к сбою или утечке памяти.
    • Я предполагаю, что ваша программа использовала CRT в статической библиотеке, тогда как OpenCV имел CRT в DLL.
    • Наличие CRT статически связанных означает наличие встроенного частного CRT.
    • Следовательно, у вас было два ЭЛТ: один в вашей программе, один в DLL, используемый OpenCV.
    • Теперь, когда вы изменили свою программу на использование CRT в DLL, они используют одну и ту же DLL, которая загружается только один раз за процесс, поэтому теперь вы только на CRT.
+0

================================== ПРОВЕРКА ОСТАНОВКИ 00000006: pid 0x254C: Поврежденная куча указатель или использование неправильной кучи. \t 087D1000: рукоятка кучи, используемая в вызове. \t 087025B8: Блок кучи, участвующий в операции. \t 00000A48: Размер блока кучи. \t 07DE1000: кучи, где блок был первоначально выделен. ======================================= Это верификатор остановка не продолжимы. Процесс будет прекращен , когда вы используете команду отладки 'go '. – AutomaticHourglass

+0

Это результат, который я получаю от верификатора приложения, я также не мог найти полезную информацию об этом в Интернете. Есть идеи? – AutomaticHourglass

+0

Как вы можете видеть, куча не повреждена, но вместо этого удаляется неправильный указатель. Проверьте стек вызовов в момент этого нового сбоя. Я считаю, что это в деструкторе вектора, и я уже объяснил причину этого: вы связываете OpenCV, скомпилированный с разными настройками компилятора или Debug/Release. – Codeguard

0

Я думаю, что у вас есть проблема смешивания отладки исполняемого файла с DLL выпуска. Вероятно, они используют разные кучи и/или распределители. Этот код, вероятно, что взрывать:

Mat o; 
descriptorExtractor->compute(img,keypoints,o); // fills 'o' by reference, allocation happens in release library 
return o; 
// function exists, freeing 'o', free happens in debug binary 

Проверьте, чтобы увидеть, если OpenCV есть отладочная версия DLL, и если да, измените настройки проекта MSVC, чтобы использовать его.

Или, вы можете «исправить», добавив намеренную утечку:

Mat* o = new Mat(); 
descriptorExtractor->compute(img,keypoints,*o); 
return *o; 
// HACK! function exists, leaking o... but so what? 
+0

Dll issue, проверил, что трижды, все библиотеки 2410 (а не d в нем). Я пробовал использовать указатели для o, но такая же ошибка случается (повреждение кучи). Есть ли в openCV любые другие DLL, которые должны быть включены/связаны в проектах (я связываю только файлы .lib без d в своих именах) – AutomaticHourglass

Смежные вопросы