08-内存管理的缺陷
5.5 内存管理的缺陷
在使用GC的语言中,可将处理内存的工作从程序员那里抽离出来。你可以在代码中声明和使用变量,不过如何释放它们并不需要你去操心。另一方面,底层的系统编程语言(例如C/C++)无法将这些细节与程序员隔离,并且几乎不提供任何安全性。这里,程序员负责通过手动调用free函数来释放内存,如果我们看一下与内存管理有关的当前软件中常见的漏洞和暴露(Common Vulnerabilities & Exposure,CVE),就会发现我们对此并不擅长!程序员可以通过错误的顺序分配和释放值来轻易构造出难以调试的错误,这些错误甚至可能是由于忘记释放已使用的内存或非法转换指针导致的。在C语言中,没有什么可以阻止你创建一个指向整数的指针,若在某处取消对它的引用,会导致程序在运行时崩溃。此外,由于编译器检查较少,因此在C语言中创建漏洞非常容易。
最令人担忧的情况是释放在堆上分配的数据。堆内存需要谨慎使用,如果没有释放,堆中的值可能在程序的生命周期中永久存在,并且最终会导致应用程序被内核中的内存越界(Out Of Memory,OOM)守护程序终结。在运行时,会由代码中的错误或开发人员的错误而导致忘记释放内存,或者访问超出内存布局之外的地方,以及在受保护的代码段中取消引用的内存地址。发生这种情况时,进程会从内核接收陷阱指令,这时我们将看到分段错误的异常信息,然后进程被终止。因此,我们必须确保进程与内存的交互安全性。作为程序员我们必须谨小慎微地对待malloc和free函数调用,或者使用内存安全的语言为我们处理这些细节。