如何在不包括Windows.h的情况下获取DebugBreak的声明? [英] How to get a declaration for DebugBreak without including Windows.h?

查看:133
本文介绍了如何在不包括Windows.h的情况下获取DebugBreak的声明?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个C ++库.我们提供了一个自定义断言,并放弃了Posix NDEBUGassert(下面的背景).

We have a C++ library. We are providing a custom assert and abandoning Posix NDEBUG and assert (back story below).

断言在Windows下看起来像这样

The assert looks like so under Windows:

#  define CRYPTOPP_ASSERT(exp) {                                  \
    if (!(exp)) {                                                 \
      std::ostringstream oss;                                     \
      oss << "Assertion failed: " << (char*)(__FILE__) << "("     \
          << (int)(__LINE__) << "): " << (char*)(__FUNCTION__)    \
          << std::endl;                                           \
      std::cerr << oss.str();                                     \
      DebugBreak();                                               \
    }                                                             \
  }

我们遇到的问题是,我们必须包含<windows.h>,即使定义了WIN32_LEAN_AND_MEAN,它也会带来很多额外的麻烦.一些额外的麻烦,例如minmax,会破坏C ++编译.实际上,测试我们的更改使我们感到震惊.

The problem we are having is, we have to include <windows.h>, and it brings in a lot of extra cruft, even with WIN32_LEAN_AND_MEAN defined. Some of the extra cruft, like min and max, breaks C++ compiles. In fact, testing our changes broke us.

我们通过<windows.h>进行了搜索,以查找仅调试包含"类型定义,但找不到.我们还尝试根据

We looked through <windows.h> searching for a "debug includes only" type define but we could not find it. We also tried adding extern void WINAPI DebugBreak(void); according to Microsoft's docs on DebugBreak, but it resulted in compile errors due to redefined symbols.

添加NO_MIN_MAX(我认为这是宏)不是一种选择,因为当定义从头文件交叉花粉进入用户代码时,我们将在用户程序中更改定义.相关信息,请参见 #include指令的限制范围和朋友.

Adding NO_MIN_MAX (I think that's the macro) is not an option because we are changing defines in user programs when the define cross-pollinates out of our header and into user code. Related, see Limiting Scope of #include Directives and friends.

不能使用#pragma push_macro#pragma pop_macro,因为我们支持VC ++ 6.0之前的Microsoft编译器.最早的实用程序是VS2003.

Using #pragma push_macro and #pragma pop_macro is not an option because we support Microsoft compilers back to VC++ 6.0. The earliest the pragmas are available is VS2003.

由于中断,我们 要包含<windows.h>.如何在不包括Windows.h的情况下获取DebugBreak的声明?

Because of the breaks, we do not want to include <windows.h>. How can I get a declaration for DebugBreak without including Windows.h?

谢谢.

这是一个简化的案例:

// cl.exe /c assert.cpp

#include <algorithm>

// #include <windows.h>
// #ifndef WINAPI
// # define WINAPI __stdcall
// #endif
// extern void WINAPI DebugBreak(void);

#define MY_ASSERT(exp) { \
   if (!(exp)) {         \
     DebugBreak();       \
   }                     \
}

void dummy(int x1, int x2)
{
    MY_ASSERT(x1 == std::min(x1, x2));
}

这是使用我们的extern声明模拟用户程序时的错误.此测试在安装了VS2012和VS2013的Windows 8.1 x64上进行.我们还使用了开发人员命令提示符.

Here's the error when simulating a user program with our extern declaration. This test occurred on Windows 8.1 x64 with VS2012 and VS2013 installed. We also used a developer command prompt.

Microsoft (R) C/C++ Optimizing Compiler Version 18.00.21005.1 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

assert.cpp
assert.cpp(11) : warning C4273: 'DebugBreak' : inconsistent dll linkage
        C:\Program Files (x86)\Windows Kits\8.1\include\um\debugapi.h(70) : see
previous definition of 'DebugBreak'
assert.cpp(21) : error C2589: '(' : illegal token on right side of '::'
assert.cpp(21) : error C2059: syntax error : '::'
assert.cpp(21) : error C2143: syntax error : missing ';' before '{'

当我们检查<debugapi.h>时,我们会看到:

When we inspect <debugapi.h> we see:

WINBASEAPI
VOID
WINAPI
DebugBreak(
    VOID
    );

WINBASEAPI扩展为其他宏.我认为我们无法在所有平台上都能正常使用它们.

WINBASEAPI expands into additional macros. I don't think we are going to be able to get them all right across all platforms.

我们有一个跨平台的C ++安全库,最近它捕获了 CVE-2016- 7420 .由于断言可能导致数据丢失,因此将其归类为信息披露.当敏感数据传出到文件系统(核心转储和崩溃报告)时,会发生丢失.并移交给第三方(Apple通过CrashReporter,Ubuntu通过Apport,Microsoft通过Windows Error Reporting,开发人员等).

We have a cross-platform C++ security library and it recently caught CVE-2016-7420. It was classified as an information disclosure due the potential data loss if an assert fired. The loss occurs when the sensitive data is egressed to the file system (core dumps and crash reports); and egressed to third parties (Apple via CrashReporter, Ubuntu via Apport, Microsoft via Windows Error Reporting, developers, etc).

因为我们的Makefile和Visual Studio解决方案很好地配置了库,所以断言从未在生产/发布版本中触发过.在生产/发布版本中,将删除断言,并由C ++ throw()处理错误情况.这些断言存在于调试/开发人员配置中,因此代码将自行调试,并减轻程序员的工作负担.

The asserts never fired in production/release for us because our Makefile and our Visual Studio solution well configured the library. In production/release builds, the asserts are removed and a C++ throw() handles the error condition. The asserts are present in debug/developer configurations so the code will debug itself, and relieve the programmer from the task.

经过分析,我们意识到记录发行/生产版本必须使用-DNDEBUG"不完整补救措施.人们不会阅读文档.如果RTFM能够正常工作,那么现在就已经发生了.另外,CMake不会定义它,Autotools不会定义它,Eclipse不会定义它,依此类推.实际上,我们处于CVE之前的水平.我们所做的就是在不降低风险的情况下将责任推卸进来.

After we analyzed it, we realized documenting "release/production builds must use -DNDEBUG" is an incomplete remediation. Folks won't read the docs; if RTFM was going to work, then it would have happened by now. In addition, CMake won't define it, Autotools won't define it, Eclipse won't define it, etc. We are effectively at the same point we were before the CVE. All we did was move the blame around without reducing the risk.

推荐答案

您可以使用内部函数,它不包含以下项即可工作:

You can use the intrinsic, it works without includes:

__debugbreak();

这篇关于如何在不包括Windows.h的情况下获取DebugBreak的声明?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆