c++ - 为什么我们不能修改 C++ 编译器来更好地在编译时捕获指针问题,而不是创建智能指针?
问题描述
如果我们可以设计智能指针来根据作用域知道何时销毁/删除堆内存。为什么我们不能设计编译器在堆内存超出范围而不被删除时进行标记?
为什么创建智能指针更实用?
我知道这不是智能指针的唯一原因和好处,但为什么这些改进实际上不能通过更改编译器来实现?
谢谢
解决方案
当您的代码足够复杂时,确定指针是否超出范围可以简化为与停止问题相当的问题——对于编译器来说,这是一个无法确定的问题。并不是说这个问题是可以解决的而是不切实际的,而是一个计算机程序来决定一个程序是否真的停止是不存在的。
减少停机问题的一个简单示例是以下伪代码:
Allocate x;
Do arbitrary tasks using x as storage;
Print x;
Deallocate x;
Do other tasks;
x
当且仅当“使用 x 作为存储执行任意任务”停止时才会泄露。
如果您考虑额外的考虑因素,例如多线程/并发执行,问题会变得更加严重。
正如 Nicol Bolas 的回答所提出的那样,还有一些方法可以隐藏编译器无法轻松检测的指针,例如通过 uintptr_t 来回传递指针,可能会使用一些双射函数对其进行混淆。
另一方面,这在运行时更容易做到。垃圾收集是一项相当成熟的技术,在 Java 虚拟机等运行时中可以看到。
此外,还有编译器帮助检测 C++ 中的泄漏和其他内存问题——clang++ 和 g++ 包括一个称为ASAN的运行时清理程序,它会在运行时警告非法访问和关闭时泄漏,尽管它不会在分配时发出警告无法访问/不再使用,但程序尚未终止。
推荐阅读
- c++ - 如何预编译不以 .h 结尾的 C++ 头文件
- java - 无法转换名称为 org.apache.hadoop.fs.FileSystem$Cache 的类。原因:org.apache.hadoop.fs.FileSystem$Cache$Key 类被冻结
- c# - Microsoft Visual Studio 显示“Table 一词附近使用了不正确的语法”
- c# - 在 .Net 中使用 Web API 和 Windows 应用程序上传文件
- ef-code-first - ef core 一对多共享子表
- c# - 无法构建 Uno Platform UWP 模板项目
- selenium - 在 Flutter Web 应用中使用 Selenium 浏览器测试的策略
- soapui - 如何使用 groovy 脚本进行断言
- android - Android-Activity和Android-Fragment有什么关系;UML 类图中的 Activity/Fragment 和 ViewModel?
- python - (tf.)keras 使用可训练的词嵌入加载保存的模型权重