【发布时间】:2021-06-11 05:22:59
【问题描述】:
让我们考虑这样的例子:
#include <memory>
int main() {
int x = 3;
std::shared_ptr<int> p{&x};
//std::shared_ptr<int> p = &x;
}
这个程序有一个双重释放错误(另请参阅:https://godbolt.org/z/T8eh13)。
如果我们用p{&x} 注释掉该行并取消注释它下面的行,编译将失败,这很好,我希望按照https://stackoverflow.com/a/304169/1923988
我的问题是:shared_ptr 是否可以以某种方式实现,以保护我们免受与 p{&x} 类似的用法(通常:获取自动变量地址的用法)?
我想答案是“不,因为被调用者只看到一个指针类型,无论调用者是使用 & 还是真正的指针变量”,但我想知道是否真的存在一些基本限制会阻止编译器区分这两种情况。
【问题讨论】:
-
编译器可能会发现微不足道的情况(就像您可以发现它并制作测试用例一样)。但是更一般的情况 - 获得已经传递了几次的原始指针的所有权 - 是不可能检查的,第一个(明显的)情况可能不值得努力。
std::make_shared是创建和拥有共享对象的首选方式,因此在进行代码检查时获取原始指针的所有权是一个危险信号。 -
将指针传递给自动本地甚至可能在您还提供自定义删除器的情况下是合理的,该删除器执行除释放指针之外的其他操作。所以这最多只能是一个警告。
-
不是双释放的bug,而是单释放的。
-
程序员不应该真正拥有现代
C++代码中随机原始指针 的所有权。原始指针应该被认为是非拥有的,这意味着你应该假设它们指向的对象已经拥有一个拥有者,而不是你。
标签: c++ c++11 reference smart-pointers