2013-07-09 3 views
6

Я пытаюсь создать массив размером 2, динамически, используя malloc. Вот мой код:Динамическое выделение памяти целочисленного массива

int *d = (int*)malloc(2 * sizeof(int)); 
d[0] = 4; 
d[1] = 5; 
d[2] = 8; 
d[3] = 9; 
d[4] = 7; 
int i; 

for (i = 0; i < 5; i++) 
    printf("%d \n", d[i]); 

Когда я запускаю этот код, он печатает 4, 5, 8, 9, 7.

Мне интересно, как было возможно выделить больше памяти (5 целых чисел), чем я запросил (2 целых числа)?

+1

Поведение вашего кода Неопределенное означает, что при разном выполнении вы можете заметить различное поведение, вы не можете заранее предсказать, что ваша программа может однажды произойти сбой. Этот код неправильный! ненадежный, к сожалению, компилятор C не сообщает об этом. –

ответ

9

Мне интересно, как он мог выделить больше памяти, чем я просил.

Это не так. Вы вызываете undefined поведение. Один из возможных результатов * заключается в том, что ваша программа, похоже, «работает».


* Возможно, самое худшее.

3

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

1

C не выполняет проверку границ. Вы топаете в память, что ваша программа не принадлежит.

1

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

4, 5, 8, 51, 1629501832

2

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

Не знаете, на какой ОС вы работаете, но если вы находитесь в Linux в любое время, когда вы не уверены, что что-то должно сработать или не запустить его через valgrind. В моем случае он скомпилировал хороший отчет обо всех ошибках с вашим кодом (в том числе не освобождая память malloc).

У меня есть три Invalid write of size 4 для трех дополнительных записей, которые вы делаете в памяти. Он также уведомил меня о недействительных памяти, что вы читаете в цикле с Invalid read of size 4 и, наконец, он дал мне некоторые статистические данные о течи в вашем коде:

HEAP SUMMARY: 
    in use at exit: 8 bytes in 1 blocks 
    total heap usage: 1 allocs, 0 frees, 8 bytes allocated 

LEAK SUMMARY: 
    definitely lost: 8 bytes in 1 blocks 

Наконец, don't cast the result of malloc.

1

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

Я не думаю, что вы понимаете силу указателя и синтаксиса, который вы использовали.Замечание о том, что следующее эквивалентно:

int arr[ 2 ] = { 1, 2 }; 
int *pi = &arr; 

// The following output is equivalent to... 
for (int i = 0; i < 2; i++) { 
    printf("arr[i] = %d.\n", arr[ i ]); 
} 

// this. 
for (int i = 0; i < 2; i++) { 
    printf("*(p + i) = %d.\n", *(p + i)); 
} 

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

int *d = (int *)malloc(2 * sizeof(int)); 

*(d + 0) = 4; // Observe you are accessing the memory location d points to. 
*(d + 1) = 5; // Observe you are accessing the memory location d + 4 bytes (or 8 if 64-bit) points to... 
*(d + 2) = 8; // ... 
*(d + 3) = 9; // ... 
*(d + 4) = 7; // Observe you are assigning a value to the memory location of d + 24 bytes (or 48 bytes if 64-bit). 

for (int i = 0; i < 5; i++) { 
    printf("%d \n", *(d + i)); 
} 

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

Я надеюсь, что это помогло! Не стесняйтесь исправить меня, если я совершу ошибку.

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