Массив, распределение, недоумение - PullRequest
0 голосов
/ 29 октября 2010
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int *numeros = malloc(sizeof(int) * 3 * 3);
    numeros[900] = 10;
    printf("%d", numeros[900]);
    free(numeros);
    return 0;
}

Почему именно это печатает 10, когда я не выделил достаточно памяти? Я почти уверен, что мне не хватает чего-то большого по указателям / и т.д.

Спасибо за помощь

Ответы [ 5 ]

14 голосов
/ 29 октября 2010

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

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

Также см. этот связанный вопрос .

1 голос
/ 29 октября 2010

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

В этом случае вы сохранили адрес памяти в numeros, а в следующем операторе ссылка *(numeros + 900), которая при обычном размере int будет 3600 байт после адреса памяти. Компилятор сгенерировал код для ссылки. Учитывая, что это неопределенное поведение, компилятор был совершенно прав, чтобы написать обидное письмо вам или вашей матери; Стандарт ничего не указывает. Конечно, он может обнаружить это и выдать ошибку во время выполнения, в которой говорится «Адрес за пределами строки в строке 7», но, к сожалению, ни один из используемых мной компиляторов не дает такой возможности.

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

1 голос
/ 29 октября 2010

Ваш размер массива равен 9. Поэтому, когда вы пытаетесь получить доступ к ячейке памяти 900, которая находится за пределами.

Ваше поведение undefined. Это означает, что иногда он может печатать ненужные значения, иногда может произойти сбой. Поэтому всегда инициализируйте ваши переменные перед использованием.

0 голосов
/ 29 октября 2010

Вы можете сделать это, потому что вы выделили свой массив из кучи, которая, вероятно, составляет не менее 32 КБ. Итак, вы делаете запись в другое место в куче, что является «законным». Если вы увеличили индекс массива до 128000 или около того, вы можете получить нарушение прав доступа. Таким образом, вы (возможно) перезаписываете некоторые другие данные, которые вы выделили, или, возможно, фактические метаданные управления кучей (заголовки блоков).

0 голосов
/ 29 октября 2010

Вы выделили память на 9 элементов с помощью malloc:

 int *numeros = malloc(sizeof(int) * 3 * 3); 
        // allocates memory of (4) *(9) bytes==36 bytes

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

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