C语言内存释放后的野指针
直奔主题:
代码大致逻辑如下:
1:先是申请了一块内存,给IP_head:
IP_head=(IP_HEAD *)calloc(1,sizeof(IP_HEAD));
2:然后把IP_head作为实参传给函数:
IPv4_dissect(IP_HEAD *ip_head);
3: 接着在
函数里面把IP_head指向的内存释放掉,并让IP_head指向NULL:
free(IP_head);
IP_head = NULL;
然后我的疑惑就产生在下面:
在IPv4_dissect函数里面居然还能对参数ip_head操作:
打印ip_head ->protocol
居然还有意义,而且是正确的!
这是为什么呢?
------解决方案--------------------收回内存了,只要还没被分配或者修改,那他的值还在那。free之后不会把那快地址清0
------解决方案--------------------此时你再这么搞只能是未定义的行为,程序可能工作,也可能crash
------解决方案--------------------
我觉得不是这样的吧。应该可以正常的使用!因为分配的那块内存free掉了,指针也指向的NULL。其它进程再分配 到这块内存的时候,就相当于给这块内存重新赋值。没有其它的什么影响!
------解决方案--------------------
正解,+1
不会被其他进程申请的,只可能会被该进程的其他线程申请。每个进程的堆空间是独立的。
如果有被其他线程重新申请到这块内存,并有写过,那你这时候 ip_head ->protocol 可能是修改后的值。
另外,C语言是值传递的,IPv4_dissect(IP_HEAD *ip_head) 函数里面的实参是IP_head的拷贝,在该函数内free掉并置为NULL,该函数外,IP_head还是指向分配的内存的地址的。
------解决方案--------------------应该是吧。指向NULL了。
------解决方案-------------------- 3: 接着在函数里面把IP_head指向的内存释放掉,并让IP_head指向NULL:
这句话,在函数里把形参置为NULL?? 形参的改变并不影响对应的实参
free内存一般情况并未被操作系统回收,只是libc里的内存管理着变为空闲的了,供下次分配用。所以并不会出现访问原来被释放的内存时并没出现SIGSEGV越界。
同时free也不会使内存被清0,因为那样开销太大。
------解决方案--------------------谁分配内存就由谁释放,尽量不要写这种代码,因为C语言没有规定free后的内存块不允许访问,因为现代操作系统的内存保护多数是页级别的,无法对内存段做保护,尤其是多线程的情况下,这样随意修改内存很可能崩掉。