попытаться буферизовать значение переполнения, выделенное функцией malloc () - PullRequest
1 голос
/ 28 марта 2012

Я немного озадачен функцией 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[...]$

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

Ответы [ 6 ]

3 голосов
/ 28 марта 2012

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 бит в экзотических системах.Конечно, в большинстве случаев вам не нужно об этом беспокоиться.

1 голос
/ 28 марта 2012

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

1 голос
/ 28 марта 2012

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

1 голос
/ 28 марта 2012

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

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

0 голосов
/ 28 марта 2012

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

Это что-то вроде языкового взлома и немного сомнительно в его использовании.

0 голосов
/ 28 марта 2012

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

...