下面的应用程序既可以使用注释掉的mallocated int,也可以使用int指针指向本地int‘a’我的问题是,在没有malloc的情况下这样做是否安全,因为我认为当函数"doit"返回时,int"a"超出了范围,而int*p什么都不指向。程序不是由于其简单性而导致seg错误,还是完全可以?
#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("%dn", *(int*)the_t->data);
doit(4);
printf("%dn", *(int*)the_t->data);
}
是的,在函数不再在作用域中之后取消引用指向本地堆栈变量的指针是未定义的行为。你只是碰巧运气不好,在你再次尝试访问内存之前,内存没有被覆盖,没有被释放回操作系统,也没有变成一个指向鼻子工厂恶魔的函数指针。
并非每个UB(未定义的行为)都会导致segfault。
通常情况下,堆栈的内存不会释放回操作系统(但可能会!),以便访问内存。但在下一次(更大的)函数调用中,指针指向的内存可能会被覆盖,所以你觉得在那里很安全的数据会丢失。
malloc()将工作,因为它存储在堆上。指针将一直保留,直到释放内存为止。
是的,并不是每个未定义的行为都会导致分割错误。
p
在从doit
返回时不指向任何东西并不重要
因为,你知道,p
也不在了。
不过,读取指向main
中不再存在的对象的指针确实很重要。这是UB,但在大多数现代平台上是无害的
更糟糕的是,你正在读取它曾经指向的不存在的对象,这就是直接的Undefined Behavior。
尽管如此,没有人必须抓住你:
可以使用局部变量';内存是否在其范围之外被访问?
顺便说一句,不要抛出malloc(和朋友)的结果
另外,请注意,不是free
的内存在所有平台上都是无害的:我可以避免用现代操作系统释放C中分配的内存吗?
是的,需要malloc
,否则指针将指向堆栈的4字节空间,如果您调用其他函数或现在创建本地变量,则堆栈的4个字节空间将被其他数据使用。
你可以看到,如果你之后用值10:调用该函数
void use_memory(int i)
{
int f[128]={};
if(i>0)
{
use_memory(i-1);
}
}