weak_ptr reset对shared_ptr有影响吗?

11

我不太习惯使用 weak_ptr,并且我面临着非常困惑的情况。我正在使用与 Visual Studio 2019 版本16.2.5 结合使用的Intel XE 2019 Composer更新5 (版本2019.5.281)。 我编译64位。 我使用标准的 C ++ 17 。

以下是我的试验解决方案的代码:

#include <memory>
#include <iostream>

using namespace std;

int main( int argc, char* argv[] )
{
    shared_ptr<int> sp = make_shared<int>( 42 );
    cout << "*sp = " << *sp << endl;

    weak_ptr<int> wp = sp;
    cout << "*sp = " << *sp << ", *wp = " << *wp.lock() << endl;

    wp.reset();
    cout << "*sp = " << *sp << endl;

    return 0;
}

我期望得到的输出是:

*sp = 42
*sp = 42, *wp = 42
*sp = 42

...但这是我得到的结果:

*sp = 42
*sp = 42, *wp = 42
*sp = -572662307

发生了什么?当关联的一个或多个weak_ptr被重置时,shared_ptr是否会被修改/失效是正常的吗?我对我得到的结果感到有些困惑。说实话,我没有预料到这个结果...

编辑1

尽管在64位配置中出现了错误,但在32位配置中没有出现。在后者的配置中,结果是预期的。

编辑2

该错误仅在Debug模式下出现。当我在Release中构建时,我得到了预期的结果。


4
无法在g++上重现(http://coliru.stacked-crooked.com/a/3cc3fd07a4975c6c),也无法在clang++上重现(http://coliru.stacked-crooked.com/a/08a48e394cfa5ba4)。 - Borgleader
2
我认为你的实现有一个 bug。gcc 产生了正确的结果 - NathanOliver
1
无法在Visual Studio 2019(v. 16.2.5)中重现。 - Frodyne
1
不,这绝对不正常。 - freakish
4
如果有帮助调试的话,"-572662307 = 0xDDDDDDDD",这是MSVC(Microsoft Visual C++)指示释放堆内存的方式。 - Eric
显示剩余16条评论
2个回答

2

看起来这是Intel ICC方面的真正漏洞;我已经报告了它。

再次感谢您帮助我找出这个问题。


1
你能在回答中添加一个指向错误报告的链接吗?这样,任何遇到相同问题的人都可以参考错误报告了解其状态。 - Sander De Dycker
我宁愿在问题被解决之后再添加评论。 - dom_beau
1
请添加链接,这将允许读者向报告添加自己的评论。 - halfer
不知道怎么回事。如果你打开了链接,需要一个英特尔账户才能看到它???也许我错了???告诉我...我已经提交了工单并且在我的账户中。 - dom_beau
也许你可以参与我在论坛上的讨论:C++编译器论坛 - dom_beau

1

看起来是调试库中的一个bug,涉及到哨兵值。可以通过使用我提到的那行代码进行简单检查:

int i = 1; cout << i << " " << ++i << endl;

如果输出是2 2而不是1 2,那么编译器不符合规范,可能仍然认为这种情况是未定义的行为。在这种情况下,使用哨兵值可能会错误地调用reset()。类似的事情也会发生在预分配静态缓冲区内创建的对象删除时,调试模式下某些实现会用哨兵值覆盖它。

64位32位DebugRelease模式下都输出1 2 - dom_beau
2
错误出现在 _Ref_count_base 的默认构造函数中,该构造函数被指定为 = default。两个成员变量 _Uses = 1_Weaks = 1 分别被设置为 10。看起来默认生成的构造函数存在问题。请参见 memory 文件... - dom_beau
@dom_beau 嗯,这值得一份报告,我们也知道C++中的初始化是非常疯狂的。 - Swift - Friday Pie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接