2015-05-02 2 views
7

Название может быть запутанным. Предположим, str является указателем, выделенным malloc. ptr, типа int*, возложенных на него и освобождается, как показано на фрагменте кода ниже:Вызывает ли освобождение int *, которое было присвоено символу char * (выделено `malloc`), вызывает Undefined Behavior?

char* str = malloc(64); 
int* ptr = str; 

free(ptr); 

Я попытался скомпилировать код выше. Он просто дает предупреждение:

source_file.c: In function ‘main’: 
source_file.c:10:16: warning: initialization from incompatible pointer type 
    int* ptr = str; 
       ^

Приведенный выше код вызывает неопределенное поведение?
Предоставляет ли приведенный выше фрагмент кода память, выделенную malloc для str?

+0

Какой у вас компилятор? Приведенный выше код дает ошибку: не может преобразовать 'char *' в 'int *' при инициализации' с gcc 4.9.2. – farukdgn

+0

Я тоже думал о том, чтобы задать этот вопрос, после вчерашнего вопроса. Спасибо за продолжение этого ... :-) – alk

+0

@farukdgn, Получил эту ошибку при компиляции с использованием g ++ в C++. GCC, похоже, скомпилирует его. Я использую GCC 4.8.1. –

ответ

11

Does the above code invoke Undefined Behavior?

Это зависит.

От C11 проекта 6.3.2.3/7:

A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned) for the referenced type, the behavior is undefined.

В качестве выравнивания для char может отличаться от int, что, вероятно, менее ограничительный, назначая char * pc к int * pi может привести к pi существам перекос.

Однако для конкретных примера, приведенного ОР:

char * pc = malloc(64); 
int * pi = pc; 

поведение будет определяться как (см Alter Mann «ы comment) malloc() гарантированно возвращает блок памяти правильно выровнена ,

От C11 проекта 7.22.3:

The pointer returned [by aligned_alloc, calloc, malloc, and realloc] if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement ...

В качестве примера, который бы привести к непредсказуемому поведению, из-за перекоса, является:

char * pc = malloc(64); 
int * pi = pc + 1; 

Does the above code snippet free the memory allocated by malloc for str?

В случае прежнее задание ввело бы неопределенное поведение, этот вопрос не имеет значения vant, поскольку что-то может случиться с UB, который уже был вызван.

Если еще предварительное назначение не сослались UB, вызов free() бы совершенно де-выделить блок памяти, на который ссылается, как преобразование обратно значение указателя из int * в void *, как первоначально предусмотрено malloc(), хорошо определены.

С C11 проекта 6.3.2.3/7 (продолжение /):

Otherwise, when converted back again, the result shall compare equal to the original pointer

и

Из C11 проекта 6.3.2.3/1:

A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer

+3

Но с другой стороны: 'Блок, который дает вам malloc, должен быть выровнен так, чтобы он мог хранить данные любого типа.' –

+0

" * гарантированно будет выровнен * "не так ли? – alk

+0

@alk: Да, похоже. – alk

0

Это может вызвать UB, на основе байтов, выравнивания или такие ИНТ против полукокса типажей при обращении. Когда вы делаете malloc все, что он делает, возвращается void*, который может быть любого типа данных (а в некоторых случаях может потребоваться приведение типов). Не имеет значения, если вы поместите указатель в char * на int *, но будет разница в единицах доступа, то есть в случае ints 4 байта за один раз по сравнению с символом 1 байт за раз. Таким образом, этот код в вашем вопросе не будет вызывать UB, но доступ к памяти может быть.

Что касается второго вопроса, то звонок на ptr вызовет память, указанную str, также для освобождения. Теперь str будет свисающим указателем.

+1

"* может потребоваться typginging *" в C он никогда не будет. – alk

+0

В C++ вам понадобится приведение типов. – askmish

+3

C и C++ - это не тот же язык. Этот вопрос касается C. – alk

4

Номер. Не используется Неотложное поведение. Предупреждение - это просто несовместимые типы, которые вы можете использовать.

char* str = malloc(64); 
int* ptr = (int*) str; 
free(ptr); 

free действительно берет указатель недействительным и выше, не имеет никаких проблем. Однако, используя результат такого значения может вызывать неопределенное поведение из-за выравнивания типа int и типа char. Таким образом, преобразование char* в int* само по себе не приводит к неопределенности.

+0

В соответствии со стандартом (см. Мой ответ), если не указан тип целевого типа, только назначение уже вызывает UB. – alk

+0

Не знаете, в какой части вы ссылались, что назначение char ptr int int ptr приводит к UB. Как я сказал в ответ, только * используя * это может привести UB. –

+0

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

1

Does the above code invoke Undefined Behavior?

No.

Does the above code snippet free the memory allocated by malloc for str?

Да.

Просто для уточнения, некоторые замечания по поводу UB динамического распределения:

памяти, возвращаемой malloc совмещено принять любое возможное значение. Такая память не имеет объявленного типа, и ее эффективный тип устанавливается через хранилище.

Если вы

*ptr = 42; 

первые sizeof (int) байт блока памяти будет теперь типа int и может быть прочитана только как таковой, т.е.

float val = *(float *)ptr; 

будет UB.

Однако

*(float *)ptr = 42.0; 

будет законным, как он вновь устанавливает эффективный тип, теперь в свою очередь, делая прочитывает *ptr недействительным.

Кроме того, всегда доступно доступ к любому объекту с помощью указателей типа char или unsigned char.

+0

Мне жаль, что оказалось, что, когда я возился с мобильным телефоном 2 дня назад, я аккуратно запустил тебя. Я не могу отменить его без редактирования. –

+0

@BlueMoon: не стоит беспокоиться; технически, ваше редактирование должно читать 'char',' signed char' или 'unsigned char' - все это разные типы, хотя 2 из них будут иметь одинаковое представление;) – Christoph

+0

Право. Я в основном смотрел, чтобы сделать какое-то простое редактирование, а не что-то исправить :) –

Смежные вопросы