don*_*too 12 c c++ compiler-construction
这是释放单链表的内存的C代码.它是使用Visual C++ 2008编译的,代码可以正常工作.
/* Program done, so free allocated memory */
current = head;
struct film * temp;
temp = current;
while (current != NULL)
{
temp = current->next;
free(current);
current = temp;
}
Run Code Online (Sandbox Code Playgroud)
但是我也遇到过(甚至在书中)相同的代码:
/* Program done, so free allocated memory */
current = head;
while (current != NULL)
{
free(current);
current = current->next;
}
Run Code Online (Sandbox Code Playgroud)
如果我使用VC++ 2008编译该代码,程序崩溃是因为我首先释放当前的电流,然后分配current-> current.但显然如果我用其他编译器(例如,书籍作者使用的编译器)编译此代码,程序将起作用.所以问题是,为什么用特定编译器编译的代码工作?是因为编译器将指令放在记住current-> next的二进制文件中,尽管我释放了当前的而我的VC++却没有.我只想了解编译器的工作原理.
Mic*_*yan 18
第二个程序正在调用未定义的行为.它与编译器没有区别,而是C标准库和函数free()的实现差异.编译器将指针存储current为局部变量,但不会存储它引用的内存副本.
当你调用free()时,你放弃了传递给free()函数的指针所指向的内存的所有权.在放弃所有权后,指向的内存内容仍然是合理的,并且仍然是进程地址空间中的有效内存位置.因此,访问它们可能会起作用(请注意,您可以通过这种方式静默地破坏内存).指向非空并指向已经放弃的内存的指针称为悬空指针,非常危险.仅仅因为它看似有效并不意味着它是正确的.
我还应该指出,有可能以捕获这些错误的方式实现free(),例如每次分配使用单独的页面,并在调用free()时取消映射页面(以便内存地址为不再是该过程的有效地址).这样的实现非常低效,但是在调试模式下有时会被某些编译器用来捕获悬空指针错误.
caf*_*caf 11
执行此操作后free(current),current(current->next存储的位置)指向的内存已返回到C库,因此您不应再访问它.
C库可以随时更改该内存的内容 - 这将导致current->next损坏 - 但它也可能不会更改部分或全部内容,特别是很快.这就是为什么它适用于某些环境,而不是其他环境.
这有点像驾驶红色交通灯.有时你会逃脱它,但有时候你会被一辆卡车碾过.
| 归档时间: |
|
| 查看次数: |
750 次 |
| 最近记录: |