【问题标题】:Disabling Exceptions for MSVC禁用 MSVC 的异常
【发布时间】:2010-11-13 20:43:04
【问题描述】:

我正在尝试在 Visual Studio 2010 中完全禁用异常,并确保禁用异常处理,我进行了以下测试:

class CompilerFlagsTestExceptionConstructor
{
public:
 CompilerFlagsTestExceptionConstructor() { throw std::exception("Exceptions Enabled"); }
 ~CompilerFlagsTestExceptionConstructor() { }
};

class CompilerFlagsTests : public CPPUNIT_NS::TestFixture
{
 CPPUNIT_TEST_SUITE( CompilerFlagsTests );
  CPPUNIT_TEST( Test_NoExceptions );
 CPPUNIT_TEST_SUITE_END();
public:
 void Test_NoExceptions()
 {
  try
  {
   CompilerFlagsTestExceptionConstructor object;
  }
  catch(std::exception)
  {
   assert(!"Exceptions are enabled");
  }
 }
};

我已在属性页中检查了异常处理已禁用,并且我还在我的所有项目中禁用了 RTTI。我尝试将 /EH 设置为负数,并从命令行中省略它。

每次我运行此测试时,它都会失败并正确抛出异常

我想禁用异常处理的原因是因为目标软件是为不支持异常处理的目标架构编写的,并且会导致大量代码膨胀以适应堆栈展开。目标架构还具有可执行文件的最大大小,因此禁用异常会缩小代码并具有性能优势。我想在 windows 版本上禁用异常处理,以确保对目标的错误处理正常。

我做错了吗?这个测试会起作用吗?是否有其他方法可以强制和测试禁用异常?

谢谢!

【问题讨论】:

  • 嗯...核选项。看看这个结果如何会很有趣。

标签: c++ visual-studio-2010 unit-testing exception-handling


【解决方案1】:

这不是 /EH 所做的,它只是控制发出哪些展开处理程序。 /EHsc 确保在可能引发 C++ 异常时调用析构函数,/EHa 确保为任何异常(包括 SEH)调用它们。省略 /EH 是您想要减少处理程序开销的原因,编译器省略了异常过滤器,这些过滤器会在堆栈分配的对象上调用析构函数。将析构函数更改为:

~CompilerFlagsTestExceptionConstructor() { 
    assert(!"Something is wrong with /EH");
}

如果您想查找不需要的 try/catch 代码,那么您需要注意

警告 C4530:使用了 C++ 异常处理程序,但未启用展开语义。指定 /EHsc

【讨论】:

  • VS2010 cl 抱怨:命令行警告 D9002 : ignoring unknown option '/EH-'
【解决方案2】:

我不确定你的测试是否有意义。如果异常被禁用,行为应该是什么? throw 就变成了无操作?这就是测试表明的行为。

我希望有用地禁用异常抛出应该是编译错误,或者在禁用异常的情况下抛出应该立即终止进程。

但这是题外话。 MSVC 将针对 throw 语法发出对 _CxxThrowException 的调用。如果我们定义我们自己的版本,我们可以让它随着我们的歌曲跳舞:

#include <windows.h>
#include <stdio.h>

extern "C"
void __stdcall _CxxThrowException(void * pObject,
    _s__ThrowInfo const * pObjectInfo)
{

  printf("Nope\n");
}

struct a
{ };

int main()
{
  try {
  throw a();
  } catch(const a&) {
    printf("Caught an exception\n");
  }
}

这个程序打印出来

没有

当然,提供此信息纯粹是为了娱乐目的,并且您正在执行此操作的上下文与错误处理逻辑相匹配。例如,我希望您不打算将 Windows 版本的程序提供给这样的任何人。

【讨论】:

  • 嘿,不,我不打算发布这个的 win32 版本。当我尝试覆盖它时,我得到一个奇怪的编译错误,说这是第二次声明该函数。奇怪的是我只有一个源文件,它是我声明的第一个函数(在包含任何头文件之前)。阅读 MSDN 文档说它是编译器创建的函数,似乎没有覆盖。
  • 你不想声明它,你只想实现它。它是隐式声明的(如 _s__ThrowInfo 类型)。您可能需要与链接器做一些斗争,我仅使用 SDK 中的 cl.exe 编译的这个示例程序。
  • 使用您提供给我的内容,以及一点谷歌搜索,给了我以下链接:drdobbs.com/184416600
【解决方案3】:

/EHsc- 应该可以解决问题(至少在 msvc 14 上可以)

【讨论】:

  • 这会产生以下警告:Warning D9025 overriding '/EHc' with '/EHc-'
  • 根据 Microsoft docs for the command line options for cl.exe,/EHsc- 等效于 /EHs,它告诉编译器您需要标准 C++ 异常处理,但它可以假定 extern "C"函数永远不会抛出。这不是问题所要求的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-30
  • 2015-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-23
  • 1970-01-01
相关资源
最近更新 更多