好吧,imo,此时出现的段错误不是因为您尝试释放以前未分配的内存,而是因为您尝试引用操作系统未授予您权限的内存地址而发生段错误给你(这是分段错误的定义)。
一些实验,比如你会在 valgrind 中运行你的示例代码,你会得到这个作为输出:
==6945== 无效的 free() / delete / delete[]
==6945== 在 0x402265C: 空闲 (vg_replace_malloc.c:323)
==6945== by 0x80483D5: main (bla.c:6)
==6945== 地址 0x7 没有被堆栈、malloc 或(最近)释放
==6945==
==6945== 错误摘要:来自 1 个上下文的 1 个错误(抑制:来自 1 个的 11 个)
==6945== malloc/free:退出时使用:1 个块中的 4 个字节。
==6945== malloc/free:1 个分配,1 个释放,4 个字节分配。
所以这是一个内存泄漏'pur sang'。现在假设您将更改代码,以便您尝试释放的指针“靠近”您分配的指针(因此操作系统仍然知道您可以访问它,操作系统不会授予字节边界上的内存访问权限)。假设我们这样修改代码:
int main(){
int* c;
c = (int*)malloc(sizeof(int));
c++;
free(c);
return 0;
}
运行此应用程序时,您将不再收到分段错误(由内核发出),而是来自 glibc(malloc() 和 free() 的所有者)的警告
edb@Flying-Spaghetti-Monster:/tmp$ ./a.out
*** 检测到 glibc *** ./a.out: free(): 无效指针:0x0804a00c ***
...接着是一个痕迹
所以你试图释放一些内核知道它属于你的内存,但 glibc 不记得把它交给你了。如果您在 valgrind 中运行它(通过替换 libc 中的 free()、malloc()、realloc()、... 函数并自行执行记帐),您将得到以下输出:
==6955== 无效的 free() / delete / delete[]
==6955== 在 0x402265C: 空闲 (vg_replace_malloc.c:323)
==6955== by 0x80483D2: main (bla.c:5)
==6955== 地址 0x418a02c 在大小为 4 的块分配后为 0 字节
==6955== 在 0x4022AB8: malloc (vg_replace_malloc.c:207)
==6955== by 0x80483C0: main (bla.c:3)
==6955==
==6955== 错误摘要:来自 1 个上下文的 1 个错误(抑制:来自 1 个的 11 个)
==6955== malloc/free:退出时使用:1 个块中的 4 个字节。
==6955== malloc/free:1 个分配,1 个释放,4 个字节分配。