15

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

我正在考虑类似 Java 的东西,例如,在 Java 应用程序中不可能有悬空指针。

4

2 回答 2

11

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

是和不是。

即使您使用非常严格的标准,这样做也会将您限制在 C++ 语言的一个非常狭窄的子集中。例如,十的幂(开发安全关键代码的规则)说您应该完全禁用堆使用。但是,仅此一项并不能阻止您创建内存损坏。

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

我不认为有确定的方法可以确保您的代码完全安全,但是有一些最佳实践可以帮助您确保尽可能少地出现问题。

以下是一些建议:

  • 如前所述,完全禁止堆使用可能会帮助您摆脱所有内存管理问题,但它并不能完全解决问题,因为它不会让您摆脱例如。杂散指针写入。
  • 我建议您阅读有关“三、五和零规则”的内容,其中解释了您需要注意的一些事情。
  • 与其自己管理内存,不如使用智能指针等shared_ptrunique_ptr当然,如果你愿意,你仍然可以滥用这些。(例如shared_ptr,如果您有循环引用,则不会帮助您...)
  • 使用内存检查工具,如valgrind,它可以帮助您发现问题并验证您的代码没有错误。

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

于 2017-01-12T15:17:54.480 回答
0

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

不。

但是对于 Java 也是如此。虽然 Java 在技术上不允许内存泄漏,但如果您不注意,它在实践中确实存在内存泄漏(和其他资源泄漏)。

一个在 Android 世界中广为人知的经典示例是,当程序运行的时间越长,侦听器实例的集合就会不断增长,因为侦听器会忘记注销自己。当侦听器是某个窗口或视图类的实例时,这可能会迅速导致数百 MB泄漏在 GUI 应用程序中,该类将自身保持对大图形的引用。由于所有这些内存仍然可以访问,垃圾收集无法清理它。

从技术上讲,您没有丢失指针(它仍在集合中)这一事实对您毫无帮助。恰恰相反; 这是泄漏的原因,因为它阻止了垃圾收集。

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


坏消息就这么多。

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

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

还有用于 C++ 的 Boehm 垃圾收集器,但我从未亲自使用过它。

于 2017-01-12T16:20:23.703 回答