我可以控制gcc是否在函数主体内部/外部放置引发异常的代码?

时间:2019-04-09 19:39:27

标签: exception gcc

考虑一下:

void test_throwing_function ()
{
    if (0 == function_1 ())
        throw std::logic_error (__PRETTY_FUNCTION__);

    function_2 ();
}

我在GCC上编译了此代码(调试版本,没有优化),并以简略的伪机器代码进行了编译,结果是这样

call function_1
test result, 0
jne do_not_throw
call allocate_exception
call std::logic_error::logic_error
call throw_exception
label do_not_throw:
call function_2
return

替代实现看起来像这样

call function_1
test result, 0
je do_throw
call function_2
return
label do_throw:
call allocate_exception
call std::logic_error::logic_error
call throw_exception

经过优化的构建似乎使用了第二种方法,正如我所期望的那样。

我有引发很多异常的代码,并且我也希望能够在调试器中读取机器代码,而不会看到异常将垃圾混入正常流程中。

有没有办法告诉gcc在未优化的版本中使用第二种实现方法?

1 个答案:

答案 0 :(得分:0)

不,似乎没有办法告诉gcc在-O0处进行此重新排序。它由-freorder-blocks标志控制:

$ g++ -O 1.c -S -o- | egrep '(ret|call.*logic_error)'
        ret
        call    _ZNSt11logic_errorC1EPKc@PLT

,通过-fno-reorder-blocks,我们得到-O0的行为:

$ g++ -O -fno-reorder-blocks 1.c -S -o- | egrep '(ret|call.*logic_error)'
        call    _ZNSt11logic_errorC1EPKc@PLT
        ret

但是该标志仅在启用优化后才有效。这是gcc/bb-reorder.c中的相关部分(通过的gate方法表明是否执行了该操作):

  virtual bool gate (function *)
    {
      if (targetm.cannot_modify_jumps_p ())
        return false;
      return (optimize > 0
              && (flag_reorder_blocks || flag_reorder_blocks_and_partition));
    }

确实,在没有-freorder-blocks的情况下传递-O[123s]无效。

AFAIK,大多数优化过程都是这种情况。我不知道是否有理由不允许用户在-O0进行此特定的优化。您可以尝试调整上面的代码并构建gcc的自定义版本以找出;-)

此外,也许有一种诱使gcc生成所需代码的方法,但我对如何做到这一点一无所知。