Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Попытаться буферизовать значение переполнения, выделенное malloc()

Автор вопроса: JackОтветов: 6

Я немного запутался в функции malloc().

если sizeof(char) равно 1 byte и функция malloc() принимает N байтов в качестве аргумента для выделения, то, если я это сделаю:

char* buffer = malloc(3);

Я выделяю буфер, который может хранить 3 символа, верно?

char* s = malloc(3);
int i = 0;
while(i < 1024) { s[i] = 'b'; i++; }
s[i++] = '$';
s[i] = '\0';
printf("%s\n",s);

это работает нормально. и сохраняет 1024 b's в s.

bbbb[...]$

почему приведенный выше код не вызывает переполнение буфера? Кто-нибудь может объяснить?

  • Исправьте ошибку, и тайна исчезнет. Код с ошибками делает странные вещи, поэтому мы не пишем код с ошибками. David Schwartz 28.03.2012
  • Это является переполнением буфера; вы просто не делаете ничего, чтобы использовать его. C с радостью позволит вам писать по адресу памяти, если он действительно существует. Это не ракетостроение. tbert 28.03.2012
  • @tbert, пока он действительно существует, не совсем верен - если он находится за пределами адресного пространства вашего процесса, C не позволит вам писать в него. Timothy Jones 28.03.2012
  • @TimothyJones хорошо, на самом деле существует в пространстве вашей виртуальной машины; Я не уверен, что нам нужно быть такими педантичными, учитывая запутанный характер самого вопроса. tbert 28.03.2012

cmemory-managementmalloc

Ответы

Ответ 1 · рейтинг 4 · Timothy Jones

malloc(size) возвращает место в памяти, где для использования доступно не менее size байтов. Скорее всего, вы сможете писать в байты сразу после s[size], но:

  • Эти байты могут принадлежать другим битам вашей программы, что позже вызовет проблемы при выполнении.
  • Или байты могут подойти для записи - они могут принадлежать странице, которую использует ваша программа, но ни для чего не используются.
  • Или они могут принадлежать структурам, которые malloc() использовал для отслеживания того, что использовала ваша программа. Испортить это очень плохо!
  • Или они могут НЕ принадлежать вашей программе, что приведет к немедленной ошибке сегментации. Это вероятно, если вы получите доступ, скажем, s[size + large_number]

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

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


Кроме того, malloc() создает память в куче, но переполнение буфера обычно связано с памятью в стеке. Если вы хотите создать его в качестве упражнения, используйте

char s[3];

вместо. Это создаст массив из 3 символов в стеке. В большинстве систем после массива не будет свободного места, поэтому пространство после s[2] будет принадлежать стеку. Запись в это пространство может перезаписать другие переменные в стеке и в конечном итоге вызвать ошибки сегментации, например, перезаписав указатель возврата текущего кадра стека.


Еще одна вещь:

если sizeof(char) равно 1 байту

sizeof(char) на самом деле определяется стандартом всегда как 1 байт. Однако размер этого 1 байта может не равняться 8 битам в экзотических системах. Конечно, в большинстве случаев вам не нужно беспокоиться об этом.

Ответ 2 · рейтинг 1 · Alok Save

Это неопределенное поведение (UB) для записи за пределами выделенной памяти.

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

Ответ 3 · рейтинг 1 · Oleksi

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

Ответ 4 · рейтинг 1 · FatalError

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

Ответ 5 · Adrian

Вы переполняете буфер. Это зависит от того, какую память вы переполняете, чтобы получить сообщение об ошибке.

Ответ 6 · Jeeva

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

Это немного языковой хак, и немного сомнительно его использование.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы