2010-04-27 5 views
0

Пожалуйста, взгляните на этот фрагмент кода. Я выделяю один байт для первой переменной и другой байт для второго. Однако, похоже, компилятор выделяет больше (или я чего-то не хватает). Программа выводит обе строки, хотя их длина больше одного байта.c: распределение памяти (что происходит)

void main() { 
    char* some1 = malloc(1); 
    sprintf(some1,"cool"); 
    char* some2 = malloc(1); 
    sprintf(some2,"face"); 
    printf("%s ",some1); 
    printf("%s\n",some2); 
} 

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

+2

Кстати: это тролль, а не круто, если вы имеете в виду то, что я думаю. – GManNickG

+0

Какой тип 'main()' return? Я дам вам подсказку: он возвращает 'int', а не' void'. –

ответ

7

Вы вызываете неопределенное поведение. Абсолютно все может произойти в этот момент, включая то, что вы можете ожидать.

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

7

Вы выделяете один байт, затем перераспределяете границы выделенной памяти. sprintf не проверяет границы (его друг, snprintf делает проверку границ).

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

+0

вот что я подумал. Но после выполнения программы печатается «крутое лицо». – facha

+2

Скомпилируйте с различными флагами оптимизации и посмотрите, что произойдет. Бетча происходит что-то другое. –

+2

Не требуется, чтобы программа выводила что-то другое. Программисту необходимо убедиться, что правильная вещь происходит. (В случае современных компьютеров на самом деле будет выделен 8-байтовый или больший фрагмент, но вы не должны зависеть от этого.) Если вы хотите, чтобы ваши проверки sprintf были отмечены, используйте 'snprintf (some1, 1, cool "); вместо этого. Обратите внимание на «n» в названии. –

2

Неопределенное поведение!

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

2

Вы выделяете «по крайней мере» 1 символ для своего массива и затем бросаете в него 5 символов (4 для строки, 1 для \ 0). Обычно вы переписываете память вне своего массива, и это не очень хорошая идея.

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

1

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

Используйте программу, такую ​​как Valgrind, и это скажет вам, что вы сделали что-то не так.

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