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

Я столкнулся с проблемой, которую не понимаю, вот мой код:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <cstdlib>
using namespace std;

int main(int argc, char **argv)
{
char *format = "The sum of the two numbers is: %d";
char *presult;
int sum = 10;
presult = (char *)calloc(sizeof(format) + 20, 1);   //allocate 24 bytes

sprintf(presult, format, sum);  // after this operation,
// the length of presult is 33
cout << presult << endl;

presult[40] = 'g';   //still no segfault here...
delete(presult);
}

Я скомпилировал этот код на разных машинах. На одной машине то SizeOf (формат) 4 байта, а для другого размер (формат) составляет 8 байтов; (На обеих машинах голец занимает всего один байт, что означает SizeOf (формат *) равно 1)

Однако, неважно, на какой машине результат все равно меня смущает. Поскольку даже для второй машины выделенная память для использования составляет всего 20 + 8, что составляет 28 байт, и, очевидно, длина строки составляет 33, что означает, что по крайней мере Нужно 33 байта. Но есть НЕТ ошибки сегментации происходит после запуска этой программы. Как вы можете видеть, даже если бы я попытался разыменовать предсульт в позиции 40, программа не дает сбоя и не отображает информацию о сбоях.

Может ли кто-нибудь помочь объяснить, почему? Огромное спасибо.

0

Решение

Доступ к нераспределенной памяти неопределенное поведение, Это означает, что вы можете получить сегфо (если вам повезет) или нет.

Или ваша программа может свободно отображать котят на экране.

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

2

Другие решения

Потому что неопределенное поведение не определено. Это не «определено к краху».

1

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

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

1

Чтобы ответить на это: «результат все еще сбивает меня с толку. Потому что даже для второй машины выделенная память для использования составляет всего 20 + 8, что составляет 28 байт, и, очевидно, строка имеет длину 33, что означает, что по крайней мере 33 байта необходимы.»

sizeof (some_pointer) == sizeof (size_t) в любой инфраструктуре. Вы тестировали на 32-битной машине (4B) и на 64-битной машине (8B).

Вы должны указать malloc количество байтов для выделения; sizeof (ptr_to_char) не даст вам длину строки (количество символов до ‘\ 0’).

Кстати, strlen делает то, что вы хотите: http://www.cplusplus.com/reference/cstring/strlen/

1
По вопросам рекламы [email protected]