std::unique_ptr 取消引用异常未在 try-catch 块中捕获

Posted

技术标签:

【中文标题】std::unique_ptr 取消引用异常未在 try-catch 块中捕获【英文标题】:std::unique_ptr dereference exception not catch-ed in try-catch block 【发布时间】:2018-05-22 09:49:50 【问题描述】:

假设我有:

struct test 
    bool a;
    int b;
;

int main()

    std::unique_ptr<test> ptr;
    // don't init the ptr

    try
    
        if (!ptr->a)
        
            std::cout << "ok" << std::endl;
        
    
    catch (const std::exception &ex)
    
        std::cout << "ex: " << ex.what() << std::endl;
    

    return 1;

所以在这里我设置了一个唯一指针,但我没有初始化它(在更大的代码库中模拟它)但我想捕获异常。

问题是我的异常没有被调用——我只是崩溃了(内存访问错误)

我阅读了一些类似的问题(但不完全相同),这些问题表明我通过引用传递了异常 - 但这不起作用。

那么是否有可能捕获 unique_ptr 取消引用异常?

编辑:我应该补充一点,这是在运行 MSVS2012 可执行文件的 Windows 7 机器上 - 如果它是相关的!

【问题讨论】:

取消引用未初始化的指针是未定义的行为,不会引发异常。 @RichardCritten 哦....有没有办法做我想做的事? - 我有一个 unique_ptr 的列表 - 我试图通过在它周围放置一个 try 块来避免单独检查每个...但是如果它没有引发异常,那么我想我必须在每个周围做if (ptr) ... 为什么你拥有不拥有任何东西的智能指针 (std::unique_ptr)?这感觉像是一个 XY 问题。 @RichardCritten 我正在使用智能指针,这样我就不必担心垃圾收集等等......在我的代码中,当我创建一个新指针时,构造函数(类型为指向 ) 可能会失败,如果是这样,智能指针实际上是 nullptr。所以我想测试一下这个条件...... 当正在构造的对象失败并且不创建std::unique_ptr`时抛出异常。 【参考方案1】:

那么是否有可能捕获 unique_ptr 取消引用异常?

没有要捕获的unique_ptr 取消引用异常。

作为documentation says,

如果get() == nullptr,则行为未定义

您可以使用这种类似 Java 的行为轻松编写自己的智能指针,但这确实意味着在 每个 取消引用时都要为测试和分支付费,这通常看起来很愚蠢。

对于cmets中描述的略有不同的问题:

我有一个 unique_ptr 的列表 - 我试图通过在其周围放置一个 try 块来避免单独检查每个。

理智的解决方案可能是检查一次,而不是每次取消引用:

if(any_of(begin(ptrs), end(ptrs), logical_not<unique_ptr<test>>)

  throw MyNullPointerException();

对于后续的 cmets,您可以在构造函数中添加一个 check-and-throw 包装器。

在 C++17 中,您几乎可以通过返回 optional&lt;unique_ptr&lt;test&gt;&gt;(即,它包含填充的 unique_ptr,或根本不包含任何内容:在这种情况下,调用 value 来提取unique_ptr 会抛出 std::bad_optional_access 如果那里真的没有)。

如果你可以导入 ot(或者没有 C++17),GSL 可能会更好用gsl::not_null&lt;T&gt;。例如,您可以将这些东西存储在您的容器中

using unique_not_null = std::unique_ptr<gsl::not_null<test>>;

【讨论】:

“你可以在你的构造函数中添加一个检查并抛出包装器” - 比如gsl::not_null?

以上是关于std::unique_ptr 取消引用异常未在 try-catch 块中捕获的主要内容,如果未能解决你的问题,请参考以下文章

std::unique_ptr

对Windows HANDLE使用std :: unique_ptr

std::list< std::unique_ptr<T> >:传递它

C++:通过引用 unique_ptr 对象使 unique_ptr 为空

深入了解C++ (15) | 源码分析auto_ptr & unique_ptr 设计

移动语义的一切