2015-02-19 2 views
2

Следующее приложение работает как с закомментированным malloced int, так и при использовании указателя int для указания на локальный int 'a.' Мой вопрос в том, можно ли обойтись без malloc, потому что я думаю, что int 'a' выходит за рамки, когда функция doit возвращается, оставляя int * p ни на что. Не отличается ли программа от сбоев от ее простоты или это нормально? неТребуется ли malloc для этого примера int pointer?

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

typedef struct ht { 
    void *data; 
} ht_t; 

ht_t * the_t; 

void doit(int v) 
{ 
    int a = v; 
    //int *p = (int *) malloc (sizeof(int)); 
    //*p = a; 
    int *p = &a; 

    the_t->data = (void *)p; 
} 

int main (int argc, char *argv[]) 
{ 
    the_t = (ht_t *) malloc (sizeof(ht_t)); 
    doit(8); 
    printf("%d\n", *(int*)the_t->data); 
    doit(4); 
    printf("%d\n", *(int*)the_t->data); 
} 
+0

[Не набрасывать результат 'malloc()'] (http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) –

ответ

5

Да, разыменования указателя на локальную переменную стека после функции больше не находится в объеме не определено поведение. Вам просто не повезло, что память не была перезаписана, выпущена обратно в ОС или превращена в указатель функции на фабрику демонов в нос, прежде чем вы попытаетесь получить к ней доступ снова.

+4

Возможно, вы имели в виду: " Вам просто не повезло, что ваша реализация в этом контексте не сбой »? – Deduplicator

+2

@Deduplicator Да, но я решил дать несколько примеров того, какие другие проблемы, с которыми он мог столкнуться, может быть полезен. – IllusiveBrian

3

Не каждый UB (неопределенное поведение) приводит к segfault.

Обычно память стека не возвращается в ОС (но может быть!), Так что доступ к этой памяти будет работать. Но при следующем (большем) вызове функции память, на которую указывает указатель, может быть перезаписана, поэтому ваши данные, которые вы чувствовали, как безопасные, были потеряны.

0

Не имеет значения, что p не указывает ни на что по возвращении с doit.
Потому что, вы знаете, p уже не существует.

Неважно, что вы читаете указатель на не существующий ранее объект в main. Это UB, но безвредный на большинстве современных платформ.
Хуже того, вы читаете несуществующий объект, на который он указывал, который является прямым Undefined Behavior.

Тем не менее, никто не обязан поймать вас:
Can a local variable's memory be accessed outside its scope?

как в сторону, Don't cast the result of malloc (and friends).
Кроме того, следует помнить, что не free -ную памяти не безвредна на всех платформах: Can I avoid releasing allocated memory in C with modern OSes?

0

Да, malloc нужен, в противном случае указатель будет указывать на 4-байтового пространства стека, который будет использоваться другими данными, если вы вызвали другие функции или создали теперь локальные переменные.

Вы можете видеть, что если вы вызываете эту функцию после со значением 10:

void use_memory(int i) 
{ 
    int f[128]={}; 
    if(i>0) 
    { 
     use_memory(i-1); 
    } 
} 
1

таНос() внутри вызова функции будет работать, потому что он хранит в куче. Указатель остается до тех пор, пока вы не освободите память.

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

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