本章总结《C和C++安全编码》中内存管理相关的内容。
常见的C++内存管理错误
1 未能正确检查分配失败
下面是一个错误的检测分配内存是否成功的例子:
1 | int *ip = new int; |
由于 new 在内存分配失败时会抛出异常,因此上面的检验条件总为真,else 分支不会被执行,可以使用 std::nothrow
来使 new 在分配失败时不抛出异常,而是返回一个空指针:
1 | T* p2 = new(std::nothrow) T; |
2 不正确配对的内存管理函数
不要混合使用 C 和 C++ 的内存分配运算符,比如使用 free() 来释放 new 分配的内存,因为这样会导致内存泄露。
1 | void test_memory_new_delete_unpaired() |
更多关于 new、delete 和内存泄漏的内容可以查看之前的笔记:【知识汇总】C++ 相关。
3 多次释放内存
为了防止多次释放内存或内存泄漏,在存放指针的容器中使用智能指针,更多关于内存泄漏、野指针和智能指针的内容可以查看之前的笔记:【知识汇总】C++ 相关。
4 释放函数抛出异常
如果释放函数通过抛出一个异常终止,那么该行为是未定义的。释放函数,包括全局的operator delete()函数,它的数组形式与其用户定义的重载,经常在销毁类类型的对象时被调用,其中包括作为某个异常结果的栈解开。允许栈解开期间抛出异常导致逃避了调用std::terminate,而导致std::abort函数调用的默认效果。这种情况可能被利用为一种拒绝服务攻击的机会。因此,释放函数必须避免抛出异常。