Пишу больше символов, чем неправильно. Почему это не подведет? - PullRequest
2 голосов
/ 16 июля 2011

Почему следующее работает, а не выбрасывает какую-то ошибку сегментации?

char *path = "/usr/bin/";
char *random = "012";

// path + random + \0
// so its malloc(13), but I get 16 bytes due to memory alignment (im on 32bit)
newPath = (char *) malloc(strlen(path) + strlen(random) + 1);

strcat(newPath, path);
strcat(newPath, "random");
// newPath is now: "/usr/bin/012\0" which makes 13 characters.

Однако, если я добавлю

strcat(newPath, "RANDOMBUNNIES");

не должен ли этот вызов произойти сбой, потому что strcat использует больше памяти, чем выделено? Следовательно, не должно

free(newPath)

также не удается, потому что он пытается освободить 16 байтов, но я использовал 26 байтов ("/ usr / bin / 012RANDOMBUNNIES \ 0")?

Большое спасибо заранее!

Ответы [ 9 ]

7 голосов
/ 16 июля 2011

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

3 голосов
/ 16 июля 2011

Весь фрагмент программы неверен.Вы предполагаете, что malloc() возвращает что-то, у которого по крайней мере первый байт установлен в 0.Как правило, это не так, поэтому даже ваш «сейф» strcat() неправильный.

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

(Кроме того, вы не должны приводить возвращаемое значение malloc().)

1 голос
/ 17 июля 2011

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

1 голос
/ 16 июля 2011

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

0 голосов
/ 16 июля 2011

Операционные системы выделяют с определенной степенью детализации, которая в моей системе составляет размер страницы 4 КБ (что типично для 32-битных компьютеров), всегда ли malloc () берет новую страницу из ОС, зависит в вашей C библиотеке времени выполнения .

0 голосов
/ 16 июля 2011

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

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

0 голосов
/ 16 июля 2011

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

0 голосов
/ 16 июля 2011

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

0 голосов
/ 16 июля 2011

Произойдет сбой и произойдет сбой в случайном порядке, в зависимости от доступности памяти сразу после памяти malloc.

Также, если вы хотите объединить произвольно, не следует заключать в кавычки.это должно быть

strcat(newPath, random);
...