2015-01-06 2 views
-1

У меня проблема при запуске моего кода в C++. У меня есть функция, и я динамически определяется двумерный массив в него, используя этот код:Ошибка повреждения кучи при освобождении массива в C++

double** childs=new double *[2]; 
for(int i=0;i<2;i++) 
    childs[i]=new double[node]; 

код работал хорошо, пока я не решил освободить этот массив в конце функции, я использовал код ниже:

for(int i=0;i<2;i++) 
    delete []childs[i]; 

delete [] childs; 

После добавления этой части кода, у меня есть проблемы во время работы и появилась ошибка отладки, как на картинке ниже:

enter image description here

Я много искал, но я не понял, в чем проблема. Я знаю, что эта ошибка предназначена для освобождения части, потому что, когда я удаляю этот код, работает хорошо.

Может ли кто-нибудь помочь мне в этом? Большое спасибо

+2

A Для без брекетов и без углублений вы просите о неприятностях. – Borgleader

+2

Возможно, вы выписываете границы выделенных массивов. Или некоторые другие массивы. –

+1

И что случилось с ['std :: array'] (http://en.cppreference.com/w/cpp/container/array) и [' std :: vector'] (http: //en.cppreference. ком/ж/CPP/контейнер/вектор)? –

ответ

1

Недостаточно кода, чтобы определить, где была перезаписана память. Но вы можете найти это место в программе, просто вставив инструкции печати, которые будут печатать все значения указателей.

Например

std::cout << childs << std::endl; 
std::cout << childs[0] << std::endl; 
std::cout << childs[1] << std::endl; 

Или вы можете попробовать следующее

std::cout << (void *)((char *)childs - sizeof(int)) << std::endl; 
std::cout << (void *)((char *)childs[0] - sizeof(int)) << std::endl; 
std::cout << (void *)) (char *)childs[1] - sizeof(int)) << std::endl; 

Или вы можете использовать цикл для вывода Чайлдс [0] и Чайлдс [1] в цикле :).

2

«Я знаю, что эта ошибка предназначена для освобождения части, потому что, когда я удаляю этот код, он работает хорошо». -> Это не обязательно так. Если вы возитесь с памятью, все может сломаться в неожиданных местах. Например, возможно, в какой-то момент вашего кода вы пишете вне своего массива, и, тем не менее, он ломается, когда пытается удалить [].

1

Проблема в том, что у вас есть код, который написал «защитные байты» выделенного пространства, а отладочная версия вашего приложения Visual C++ обнаружила, что вы это сделали.

Что такое "защитные байты"? Они представляют собой байты, написанные с информацией до и после выделенного пространства, и инициализируются некоторым значением по времени выполнения. Когда приходит время освобождать память, среда выполнения проверяет эти защитные байты, чтобы увидеть, изменилось ли значение. Если они изменились, вы совершили ошибку где-то, где вы нечаянно написали данные в область, занятую этими байтами.

Среда Visual C++ не может, на лету, обнаруживать, когда вы написали сторожевые байты. Он может обнаружить это только при освобождении. Вот почему вы считаете, что ваша программа «работает правильно», когда на самом деле она работает неправильно.

Так что найдите перезаписи, проверив индексы массива для отрицательных значений или положительных значений, которые превышают границы вашего массива.

2

Что вы действительно хотите сделать, это перебраться на сайт microsoft и захватить инструменты для отладки для окон. Я подожду ...

Используйте gflags с опцией pageheap.См. http://msdn.microsoft.com/en-us/library/windows/hardware/ff549561(v=vs.85).aspx

Pageheap изменит распределитель для вашего процесса тем, который помещает защищенные страницы до и после каждого выделения, а также освобожденные блоки. Результатом этого является то, что вы сможете обнаруживать, когда вы мгновенно получаете доступ к границам ваших распределенных данных с помощью pagefault.

Очевидно, что вы хотите запустить приложение под отладчиком, чтобы уловить эту ошибку и выяснить, что вы делаете неправильно. Кроме того, обратите внимание, что лучше сделать это с помощью сборки релиза, потому что сборка отладки будет содержать защитные байты вокруг распределений памяти, которые не имеют защиты от перебора страниц, поэтому при тестировании вы можете получить ложный отрицательный результат.

Удачи вам!

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