gpt4 book ai didi

c++ - 如何在不包含 Windows.h 的情况下获得 DebugBreak 的声明?

转载 作者:可可西里 更新时间:2023-11-01 13:55:41 25 4
gpt4 key购买 nike

我们有一个 C++ 库。我们正在提供自定义断言并放弃 Posix NDEBUGassert (下面的背景故事)。

断言在 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++ 编译。事实上,测试我们的更改让我们崩溃了。

我们翻阅了<windows.h>搜索“调试仅包含”类型定义,但我们找不到它。我们还尝试添加 extern void WINAPI DebugBreak(void);根据 Microsoft's docs on DebugBreak , 但由于重新定义符号而导致编译错误。

添加NO_MIN_MAX (我认为那是宏)不是一个选项,因为当定义从我们的 header 交叉授粉并进入用户代码时,我们正在更改用户程序中的定义。相关见Limiting Scope of #include Directives和 friend 。

使用 #pragma push_macro#pragma pop_macro不是一个选项,因为我们支持回到 VC++ 6.0 的 Microsoft 编译器。最早可用的编译指示是 VS2003。

由于中断,我们想要包括<windows.h> .如何获得 DebugBreak 的声明不包括 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 上进行。我们还使用了开发人员命令提示符。

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>我们看到:

WINBASEAPI
VOID
WINAPI
DebugBreak(
VOID
);

WINBASEAPI扩展成额外的宏。我不认为我们能够让它们在所有平台上都正常运行。


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

因为我们的 Makefile 和我们的 Visual Studio 解决方案很好地配置了库,断言从未在我们的生产/发布中触发。在生产/发布版本中,断言被删除并且 C++ throw()处理错误情况。断言存在于调试/开发人员配置中,因此代码将自行调试,并将程序员从任务中解脱出来。

我们分析之后,实现了documenting "release/production builds must use -DNDEBUG " is an incomplete remediation .人们不会阅读文档;如果 RTFM 要工作,那么它现在就会发生。此外,CMake 不会定义它,Autotools 不会定义它,Eclipse 不会定义它,等等。我们实际上处于 CVE 之前的同一点。我们所做的只是在不降低风险的情况下推卸责任。

最佳答案

你可以使用 intrinsic,它在没有包含的情况下工作:

__debugbreak();

关于c++ - 如何在不包含 Windows.h 的情况下获得 DebugBreak 的声明?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39551229/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com