2017-01-15 5 views
2

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

Почему этот код скомпилирован и работает, когда я выделил достаточно памяти всего на два символа, «он», «привет» не должен соответствовать?

Он печатает правильную длину, которая 6.

Свободный не дает ошибку.

char* testF() { 
    char *arr = (char*)malloc(2*sizeof(char)); 
    strcpy(arr, "hellos"); 
    return arr; 
} 

int main() { 
    char *arr = testF(); 
    printf("%c%c%c%c%c%c\n", arr[0], arr[1], arr[2], arr[3], arr[4], arr[5]); 
    printf("Length = %d", strlen(arr)); 
    free(arr); 

    return 0; 
} 
+0

Это не так. Это UB. –

+0

См. [Здесь] (http://stackoverflow.com/q/40271508/5021321). –

+0

Что означает UB? – Lurr

ответ

1

Это может произойти, если после области, выделенной malloc, имеется свободная память.

Но, конечно, вы должны рассчитывать на это. Доверяйте только тому, что вы выделяете.

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

+0

Так что, в принципе, если мне не повезло в более крупной программе, я пишу материал в память, где все остальное, «llos» из «hellos» сохраняется, я получаю сбой при доступе к нему? Или плохие значения? @designerman – Lurr

+1

Если вам не повезло, на какое-то время не будет крушения, и после того, как вы что-то измените, будет ... –

2

Почему этот код компиляции и работать, когда я выделил достаточно памяти для всего два персонажей, «он», «приветы» не должны быть в состоянии соответствовать?

Это undefined behaviour, потому что strcpy() вызов переполняет буфер.

Стандарт C не требует реализации, чтобы дать ошибку или предупреждения на undefined Поведение. Таким образом, вы не можете ожидать, что что-то спасет вас; ты сам по себе.

+0

Должен ли я изменить malloc на char ** arr = (char *) malloc (6 * sizeof (char)); или char ** arr = (char *) malloc (7 * размерof (char)); , чтобы правильно его хранить? – Lurr

+0

Это должно быть '7' байт, включая завершение нулевого байта. Итак, последнее. Вы также должны проверить возвращаемое значение 'malloc()', чтобы проверить, не сработало ли оно: 'if (arr == NULL) {perror (" malloc "); Выход (EXIT_FAILURE);} '. – usr

+0

@ Шива, почему 6 не 7? – Lurr

1

Единственная причина, по которой вы не получаете ошибку, состоит в том, что объем данных, которые вы копируете, может по-прежнему помещается на страницу памяти. Если бы вы случайно скопировали данные, которые привели к переполнению страницы, вы получили бы ошибку SIGSEGV (сегментации).

В заключение, это неопределенное поведение.