Что вызывает сбой моей программы при выполнении команды «free (ppMapData [i])»? - PullRequest
0 голосов
/ 12 декабря 2008

Я попытался создать динамический 2D-массив из char следующим образом:

char** ppMapData = (char**)malloc(sizeof(char*)*iMapHeight);
for (int i=0; i< iMapHeight; i++)
{
    ppMapData[i] = (char*)malloc(sizeof(char)*iMapWidth);
    //do something
}

// do something

for (int i=0; i<iMapHeight; i++)
    free(ppMapData[i]);
free(ppMapData);

Это выглядит хорошо для меня; однако, когда дело доходит до выполнения, моя программа вылетает на линии, которая вызывает free(ppMapData[i]). Есть идеи, в чем тут проблема. Большое спасибо.

Ответы [ 11 ]

8 голосов
/ 12 декабря 2008

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

Если вы используете visual studio, вы можете вызвать _CrtCheckMemory, чтобы убедиться, что вы ничего не теряете. Этот вызов работает только в сборке DEBUG.

4 голосов
/ 12 декабря 2008

Проверяли ли вы значения NULL после malloc?

2 голосов
/ 12 декабря 2008

Несколько возможных ответов:

  1. Вы уверены, что не пересекаете концы своих выделенных массивов? malloc будет хранить важную информацию сразу после вашей выделенной памяти, и если вы перезапишите ее, произойдут плохие вещи.

  2. Вы уверены, что не изменяете значения в ppMapData? Попытка освободить указатель, который никогда не был выделен, вообще плохая вещь.

  3. Какое значение i при сбое вашей программы? Это соответствует? зная, что это было бы полезно и, возможно, поучительно

Некоторые стилистические комментарии:

  • Проверьте возвращаемое значение malloc (в случае сбоя оно будет равно NULL).

  • Не приводите возвращаемое значение malloc (если вы действительно пишете C, а не C ++).

2 голосов
/ 12 декабря 2008

Если это 2D массив с фиксированным размером в обоих измерениях, я всегда предпочитаю:

char* array = (char*)malloc(iMapHeight*iMapWidth);

И доступ к нему с помощью:

char val = array[height*iMapWidth + width];

Оберните это в макрос, если вы предпочитаете:

#define GET_VAL(h, w) array[h*iMapWidth + w]

Умножение будет быстрее, чем разыменование двух указателей, чтобы найти значение.

2 голосов
/ 12 декабря 2008

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

2 голосов
/ 12 декабря 2008

Вы отметили свой вопрос «C ++». Почему бы не использовать соответствующие конструкции C ++ вместо этого? Например. vector<vector<char> > или даже (могу ли я предложить) vector<string>?

РЕДАКТИРОВАТЬ Ну да, vector<string>, вероятно, не то, что вы хотите. Тем не менее, я настоятельно рекомендую решение на C ++.

0 голосов
/ 18 декабря 2008

В качестве альтернативы joemucchiello,

char **ppMapData = malloc(iMapHeight * sizeof(char*) +
                          iMapHeight * iMapWidth * sizeof(char)));

for (int i = 0; i < iMapHeight; i++) {
    ppMapData[i] = (char *)(ppMapData + iMapHeight) + i * iMapWidth;
    /* do something */
}

/* do something */

free(ppMapData);

Это делает одно большое выделение, содержащее как массив указателей, так и массив массивов символов.

Однако, как утверждают многие другие, код, который вы разместили, работает нормально. В сегменте "// do something" должно быть что-то, что вы не опубликовали, что вызывает эту ошибку.

Например, если вы уже освободили ppMapData[i], вы не сможете снова его освободить. Некоторые люди избегают этого, устанавливая ppMapData[i] = NULL сразу после любого free(ppMapData[i]): это работает, потому что free(NULL) является законным и ничего не делает. Я предпочитаю , а не , чтобы сделать это, и исправить любой дизайн, который приведет вас к ситуации с двойным освобождением.

0 голосов
/ 18 декабря 2008

По-прежнему происходит сбой при удалении кода «сделать что-то»? Если это не так, это, вероятно, означает, что вы нарушаете память в коде «что-то делать», и именно в этом заключается ваша ошибка, а не в коде выше.

Если вы работаете на платформе, которая ее поддерживает, запустите ее через Valgrind, и найти тонкие ошибки бесценно.

0 голосов
/ 18 декабря 2008

Из кода в вопросе не похоже, что вы проверяете, успешно ли malloc. Убедитесь, что malloc не возвращает NULL в качестве первого шага. Возможно, это не ваша проблема, как

//do something

, вероятно, использует новую выделенную память, но если это не так, то malloc может потерпеть неудачу без вашего ведома, если вы не разыменовываетесь со свободной. (Я знаю, что маллок вряд ли потерпит неудачу, если вы не разрабатываете для среды с низким объемом памяти, но это все еще стоит проверить)

Во-вторых, каково значение i, когда оно падает, это почти то же самое?

Наконец, вы можете получить нам дамп ядра, проблему легче идентифицировать:)

0 голосов
/ 18 декабря 2008

Предположим, // сделать что-то большее, чем просто комментарий, убрать

// сделать что-то

код и посмотрите, все ли сбой. Добавляйте вещи обратно по одному, пока они снова не рухнут

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...