Программа отказывает только в режиме Release вне отладчика

У меня есть довольно крупная программа (> 10k строки кода C++). Это работает отлично в режиме отладки или в режиме выпуска при запуске из Visual Studio, но двоичный файл режима выпуска обычно отказывает при ручном запуске из командной строки (не всегда!!!).

Строка с удаляет, вызывает катастрофический отказ:

bool Save(const short* data, unsigned int width, unsigned int height, 
          const wstring* implicit_path, const wstring* name = NULL, 
          bool enable_overlay = false)
{
    char* buf = new char[17];
    delete [] buf;
}

Править: По запросу развернул пример.

"len" имеет длину 16 в моем тестовом сценарии. Не имеет значения, если я делаю что-то с buf или нет, это отказывает на удалении.

Править: Приложение хорошо работает без удаления [] строка, но я предполагаю, что это пропускает память тогда (так как блок никогда не освобождается). buf в никогда используемом после удалить строки. Также кажется, что это не отказывает ни с каким другим типом, чем символ. Теперь я действительно смущен.

Сообщение катастрофического отказа очень неконкретно (типичный Windows "xyz.exe прекратил работать"). Когда я нажимаю опцию "Debug the program", она вводит VS, где ошибка определяется, чтобы быть "Местоположением записи нарушения прав доступа xxxxxxxx". Это неспособно определить местоположение места ошибки, хотя "Никакие символы не были загружены ни для какого стекового фрейма".

Я предполагаю, что это - некоторый довольно серьезный случай повреждения "кучи", но как отладить это? Что я должен искать?

Спасибо за справку.

9
задан quamrana 27 February 2010 в 15:10
поделиться

7 ответов

проверяли ли вы утечки памяти где-то еще?

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

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

11
ответ дан 4 December 2019 в 11:04
поделиться

Вы пробовали просто изолировать это с помощью того же файла сборки, но кода, основанного только на том, что вы указали выше? Что-то вроде:

int main(int argc, char* argv[] )
{
    const int len( 16 );
    char* buf = new char[len + 1]; 

    delete [] buf;
}

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

Пробовали ли вы создать новый проект и разместить в нем более 10 тыс. Строк C ++? ? Возможно, не потребуется слишком много времени, чтобы доказать это. Особенно, если существующий проект был либо импортирован, либо сильно изменен.

0
ответ дан 4 December 2019 в 11:04
поделиться

Есть много возможных причин сбоев. Их всегда сложно найти, особенно когда они различаются от режима отладки к режиму выпуска.

С другой стороны, поскольку вы используете C ++ , вы можете уйти, используя std :: string вместо буфера, выделенного вручную >> есть причина для который RAII существует;)

1
ответ дан 4 December 2019 в 11:04
поделиться

Самая большая разница между запуском в отладчике и запуском самостоятельно заключается в том, что когда приложение запускается из отладчика, Windows предоставляет "отладочную кучу", то есть заполнен шаблоном 0xBAADF00D; обратите внимание, что это не куча отладки, предоставляемая CRT, которая вместо этого заполняется шаблоном 0xCD (IIRC).

Здесь - одно из немногих упоминаний Microsoft об этой функции, а здесь вы можете найти несколько ссылок об этом.

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

{{1} }
5
ответ дан 4 December 2019 в 11:04
поделиться

Вероятно, у вас где-то произошла перезапись памяти, и delete[] - это просто первый случай, когда это вызывает проблему. Но сама перезапись может находиться в совершенно другой части вашей программы. Трудность заключается в том, чтобы найти эту перезапись.

Добавьте следующую функцию

#include <malloc.h>

#define CHKHEAP()  (check_heap(__FILE__, __LINE__))

void check_heap(char *file, int line)
{
    static char *lastOkFile = "here";
    static int lastOkLine = 0;
    static int heapOK = 1;

    if (!heapOK) return;

    if (_heapchk() == _HEAPOK)
    {
        lastOkFile = file;
        lastOkLine = line;
       return;
    }

    heapOK = 0;
    printf("Heap corruption detected at %s (%d)\n", file, line);
    printf("Last OK at %s (%d)\n", lastOkFile, lastOkLine);
}

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

2
ответ дан 4 December 2019 в 11:04
поделиться

Эти две строки - первые две строки в их функции.

Если вы действительно имеете в виду то, как я это интерпретирую, то первая строка объявляет локальную переменную buf в одной функции, а delete удаляет какую-то другую buf, объявленную вне второй функции.

Возможно, вам следует показать две функции.

0
ответ дан 4 December 2019 в 11:04
поделиться

Похоже, у вас где-то в коде есть унифицированная переменная.

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

В режиме выпуска память не инициализируется, если вы явно что-то не сделаете.

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

0
ответ дан 4 December 2019 в 11:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: