Еще одна ошибка динамического выделения памяти - PullRequest
0 голосов
/ 02 июня 2010

Я пытаюсь выделить память для многомерного массива (8 строк, 3 столбца).

Вот код для распределения (я уверен, что ошибка понятна для вас)

char **ptr = (char **) malloc( sizeof(char) * 8);

for (i = 0; i < 3; i++)
    ptr[i] = (char *) malloc( sizeof(char) * 3);

Сбой происходит, когда я ссылаюсь на это:

ptr[3][0];

Необработанное исключение в 0x0135144d в xxxx.exe: 0xC0000005: Запись о нарушении доступа местоположение 0xabababab.

Есть ли рекомендуемые ссылки / материалы по этому виду предмета?

Спасибо.

Ответы [ 6 ]

8 голосов
/ 02 июня 2010

Первый malloc() неверен. Должно быть:

malloc(sizeof(char*) * 8)

A char* - это 4 байта (или 8 байтов ... см. P.S), тогда как char - это 1 байт. Когда вы пишете ptr[3], компилятор предполагает, что вы хотите получить доступ к базовому адресу ptr + 3*sizeof(char*). Таким образом, вы получите доступ к памяти, которую вы не выделяли.

P.S:

Точнее, char* - это 4 байта в 32-битных системах и 8 байтов в 64-битных системах.

6 голосов
/ 02 июня 2010

Я не знаю ни одной книги по распределению памяти, но любой вводный урок C должен объяснить это. Что касается вашей ошибки, ваш цикл for инициализирует только первые 3 строки, вместо 8 выделенных вами. Должно быть:

for (i = 0; i < 8; i++)
4 голосов
/ 02 июня 2010
char **ptr = (char **) malloc( sizeof(char *) * 8);

Раньше вы выделяли место для 8 символов. Вы хотите место для 8 указателей на символ.

Майкл указал на другую ошибку, записав первый символ из строки, которую вы никогда не выделяли.

Может помочь, если вы используете константы, например:

const int STRING_COUNT = 8;
const int STRING_LEN = 2;

char **ptr = (char **) malloc( sizeof(char *) * STRING_COUNT);
3 голосов
/ 02 июня 2010

В вашем коде есть несколько ошибок / несоответствий, но первая из них - неправильная sizeof в первом выделении. Ошибку, которую вы допустили, можно было легко избежать, если бы вы следовали рекомендациям по надлежащей практике:

(1) По возможности избегайте использования имен типов в инструкциях . Имена типов принадлежат объявлениям , а не операторам.

(2) Не приводить результат функций выделения памяти.

Первое распределение должно было выглядеть следующим образом

char **ptr = malloc( 8 * sizeof *ptr );

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

pointer = malloc( count * sizeof *pointer );

Примечание. Имена типов не упоминаются в приведенном выше утверждении.

Конечно, вы также должны принять решение о первом размере вашего 2D-массива. Вы пытаетесь выделить 8, а затем инициализируете только 3. Почему?

3 голосов
/ 02 июня 2010

ptr - это массив из 8 указателей, а не char с, поэтому первая строка должна быть:

char **ptr = (char **) malloc( sizeof(char*) * 8)

Поскольку имеется 8 указателей, цикл должен идти от 0 до 7:

for (i = 0; i < 8; i++)

Вы также можете рассмотреть вариант с менее подверженной ошибкам версией первой строки:

char **ptr = (char **) malloc( sizeof(*ptr) * 8)

И последней:

ptr[i] = (char *) malloc( sizeof(*ptr[i]) * 3);

Правилоis: всегда принимать sizeof разыменованного lvalue.Если lvalue ptr, тогда вам нужно sizeof(*ptr).ptr[i] становится sizeof(*ptr[i]).

1 голос
/ 02 июня 2010

Есть две проблемы.

Во-первых, как уже отмечали другие, ваш начальный malloc должен быть

malloc (sizeof (char *) * 8)

Во-вторых, вы инициализируете первые три элемента в массиве из 8 элементов, но ptr[3][0] относится к четвертому элементу. Таким образом крушение.

...