编写内存安全的C ++应用程序需要什么?

时间:2017-01-12 15:03:47

标签: c++ memory-management memory-safety

是否可以创建编码标准或使用可以证明可以消除C ++中任何内存管理错误的库?

我正在考虑像Java这样的东西,例如在Java应用程序中悬挂指针是不可能的。

2 个答案:

答案 0 :(得分:7)

  

是否可以创建编码标准或使用可以证明可以消除C ++中任何内存管理错误的库?

是和否。

即使您使用非常严格的标准,这样做也会限制您使用非常狭窄的C ++语言子集。例如,Power of Ten (Rules for Developing Safety-Critical Code)表示您应该完全禁用堆使用。然而,仅凭这一点并不能阻止您创建内存损坏。

我认为如果对这个问题有一个确切的答案,那么这个行业几十年前就已经解决了,但我们在这里......

我认为没有明确的方法可以确保您的代码完全安全,但有最佳做法可以帮助您确保尽可能少的问题。

以下是一些建议:

  • 如前所述,完全禁止堆使用可能可以帮助您摆脱所有内存管理问题,但它并不能完全解决问题,因为它不能帮助您避免例如。迷路指针写道。
  • 我建议您阅读有关The Rule of Three, Five and Zero的内容,其中介绍了您需要处理的一些内容。
  • 不要自行管理内存,而是使用shared_ptrunique_ptr等智能指针。但是,如果您愿意,您仍然可以滥用这些内容。 (例如,如果您有循环引用,shared_ptr将无法帮助您。)
  • 使用valgrind等内存检查工具,它可以帮助您发现问题并验证您的代码是否没有错误。

即使您遵守任何编码标准或最佳做法,也会发生错误。没有人保证你会安全。但是,通过遵循这些建议,您可以最大限度地减少错误的可能性和影响。

答案 1 :(得分:1)

  

是否可以创建编码标准或使用库   可以证明这可以消除C ++中的任何内存管理错误吗?

没有

但Java也是如此。虽然Java不技术上允许内存泄漏,但如果你不这样做,它确实会在实践中发现它们(和其他资源泄漏)注意。

一个典型的例子,在Android世界中特别熟知,就是当一个程序运行的时间越长,监听器实例的集合越来越多,因为监听器忘记取消注册自己。当侦听器是某个窗口或视图类的实例时,这会在GUI应用程序中快速导致数百MB 泄漏,从而使自己引用大图形。由于所有内存仍然可以访问,因此垃圾收集无法清除它。

你没有技术上丢失指针(它仍然在集合中)的事实对你没有任何帮助。恰恰相反;这是泄漏的原因,因为它可以防止垃圾收集。

与上述相同,虽然Java技术上不允许悬空指针,但类似的错误可能会导致您访问某个窗口或视图对象的指针,该对象仍然在您的程序的有效内存区域中但不应再存在,不再可见。虽然指针访问本身不会导致任何崩溃或问题,但其他类型的错误或崩溃(如NullPointerException)通常很快就会出现,因为程序逻辑搞砸了。

这个坏消息太多了。

好消息是,如果您遵循简单的指南,这两种语言都可以让您减少内存管理问题。就C ++而言,这意味着:

  • 尽可能使用标准集合(例如std::vectorstd::set)。
  • 将动态分配作为您的第二选择。第一个选择应该始终是创建一个本地对象。
  • 如果您必须使用动态分配,请使用std::unique_ptr
  • 如果一切都失败了,请考虑std::shared_ptr
  • 仅当您实现某个低级容器类时才使用裸new,因为现有的标准容器类(如std::vectorstd::set)不适用于您的用例。不过,这应该是极为罕见的情况。

还有Boehm garbage collector for C++,但我从未亲自使用过它。