小编mod*_*ine的帖子

使用errno作为C++中的异常参数的意外控制流(compiler-bug?)(g ++)

当使用C++异常来传输errno状态时,g ++(4.5.3)为以下代码生成的编译代码

#include <cerrno>
#include <stdexcept>
#include <string>

class oserror : public std::runtime_error {
private:
    static std::string errnotostr(int errno_);
public:
    explicit oserror(int errno_) :
        std::runtime_error(errnotostr(errno_)) {
    }
};

void test() {
    throw oserror(errno);
}
Run Code Online (Sandbox Code Playgroud)

是出乎意料的(在Linux上,x86_64)

    .type   _Z4testv, @function
    ...
    movl    $16, %edi
    call    __cxa_allocate_exception
    movq    %rax, %rbx
    movq    %rbx, %r12
    call    __errno_location
    movl    (%rax), %eax
    movl    %eax, %esi
    movq    %r12, %rdi
    call    _ZN7oserrorC1Ei
Run Code Online (Sandbox Code Playgroud)

这基本上意味着作为C++异常的参数的errno几乎没用,因为在调用__errno_location(这是errno的宏内容)之前调用__cxa_allocate_exception,前者调用std :: malloc而不是保存errno状态(至少据我所知,libstdc ++的eh_alloc.cc中的__cxa_allocate_exception的来源).

这意味着在内存分配失败的情况下,实际传递到异常对象的错误号将被std :: malloc设置的错误号覆盖.的std ::的malloc不保证保存现有错误号状态,无论如何,即使在成功退出的案例 - 所以上面的代码在一般情况下绝对打破.

在Cygwin,x86上,为test()编译(也使用g ++ 4.5.3)的代码是可以的,但是:

    .def    __Z4testv;      .scl    2; …
Run Code Online (Sandbox Code Playgroud)

c++ g++ exception errno

9
推荐指数
1
解决办法
509
查看次数

标签 统计

c++ ×1

errno ×1

exception ×1

g++ ×1