2016-01-29 4 views
0

Так что у меня этот маленький каверзный вопрос, мне нужно ответить:C размер функции таНос

На какой сегмент в памяти с + 9, указывающий на, если функция:

void f() 
{ 
    int *c=(int*)malloc(10); 
} 

Я думаю, что я знаю как работает malloc, и я просмотрел другие вопросы, поэтому это должно выделить 10 байт памяти и вернуть адрес первого, плюс он будет передавать его в int.

Так как sizeof(int) - это 4 байта, я думал, что не хватит места для 9 целых чисел, а c + , программа работает нормально, как будто выделено 10*sizeof(int). Так где я делаю ошибку?

+2

'c + 9' ​​- это то же самое, что и' & c [9] ', но при условии, что' c' действительно является указателем на массив из не менее 10 элементов. Это не так в вашем коде. –

+0

Я знаю это, но этот код здесь отлично работает, когда я его использую, я не делаю программу, это вопрос. Когда я делаю программу, я использую malloc (10 * sizeof (int)), например. Но это вопрос, чтобы проверить мои знания о том, как работает C. – Nebeski

+3

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

ответ

6

Ваша ошибка в том, что она работает просто отлично.

Да, возможно, он работает, да, это, вероятно, не segfault, но нет, это неверно.

Итак, потому что SizeOf (INT) составляет 4 байта, я думал, что не будет достаточно места для 9 целых чисел, и с + 9 будет указывать на некоторый объем памяти за пределами диапазона выделенной памяти

Это правильно

и будет возвращать ошибку

Но это, к сожалению, не правильно в каждом конкретном случае. ОС может выделять пространство только на полных страницах, это означает, что вы можете получить только пробел в 4096 байт (одна страница). Это означает, что хотя malloc (который реализован в пользовательском пространстве) дает вам 10 байт, ваша программа будет иметь как минимум 4096 байт от ОС. BUT: malloc будет В конечном итоге предоставит вам более нераспределенное пространство с этой страницы, а вы получите , который будет, вероятно, ввести ошибку.

TLDR: Это UB, хотя похоже, что он работает, никогда не делайте этого.

3

Программы C не возвращают ошибку, если вы выкалываете за пределы заданного диапазона памяти. Результат не определен, он может зависать или (видимо) работать нормально. Но это не нормально.

+0

Значит, я мог бы получить доступ к другой памяти программ и, возможно, сломать ее? – Nebeski

+0

Да. Или, может быть, malloc назначил 16 байт вместо 10. Но вы не можете знать. –

+2

@Nebeski нет, это невозможно в современных ОС из-за управления виртуальной памятью. – tkausl

4

Вы ошибаетесь, полагая, что неопределенное поведение подразумевает, что произойдет что-то «плохое». Доступ к c[9] в вашем случае - неопределенное поведение, так как у вас нет malloc достаточно памяти - и это то, что вам не следует делать.

Неопределенное поведение означает, что стандарт допускает любое поведение. Для этой конкретной ошибки вы часто получаете нелокализованное неправильное поведение, доступ к c[9] будет работать, по-видимому, отлично, и при выполнении этого не происходит никаких странных событий, но затем в несвязанной части кода, обращающейся к несвязанной части данных, приводит к ошибке. Часто такие ошибки могут также повредить данные, используемые системой распределения памяти, которые могут привести к неправильной работе malloc и free.

1

Вы правы в том, что malloc дает вам 10 символов (обычно 8-разрядные байты). Выделение области для int s, которая не кратно int, размер сам по себе рыбный ... но не незаконный. Результирующий адрес интерпретируется как указатель на int (обычно 32 бита), и вы запрашиваете адрес 9 int за пределы назначенной области. Это само по себе прекрасно, но попытка получить доступ - это неопределенное поведение: что-то может случиться, включая то, что вы ожидаете наивно, ничто, ни крушение, ни конец Вселенной. Что будет обычно Случается, что вы получаете назначенную память из большей области, содержащей другие объекты и свободное пространство (а дополнительные данные malloc используются для отслеживания всего беспорядка). Чтение там не причиняет вреда, пишет может повредить другие данные или испортить данные структур данных данных, приводящие к таинственным поведением/сбоям позже. Если вам повезет, новое пространство выделяется на границе, а доступ за пределы доступа дает ошибку сегментации, указывая на виновника.