在 Windows 10 x64 上使用 Visual Studio 2019 Professional。我有几个 C++ DLL 项目,其中一些是多线程的。我使用 CRITICAL_SECTION
对象来保证线程安全。
在 DLL1 中:
CRITICAL_SECTION critDLL1;
InitializeCriticalSection(&critDLL1);
在 DLL2 中:
CRITICAL_SECTION critDLL2;
InitializeCriticalSection(&critDLL2);
当我将 critDLL1 与 EnterCriticalSection
或 LeaveCriticalSection
一起使用时,在 _DEBUG
或 NDEBUG
模式下一切都很好。但是,当我使用 critDLL2 时,NDEBUG
中的“ntdll.dll”出现访问冲突(尽管 _DEBUG
中没有)。
在NDEBUG
模式下弹出消息框后,我最终能够将问题追溯到第一次使用EnterCriticalSection
。
什么可能导致 CRITICAL_SECTION
在一个项目中失败但在其他项目中有效? MSDN page没有帮助。
更新1
比较 DLL1(工作)和 DLL2(不工作)的项目设置后,我意外地让 DLL2 工作了。我通过恢复到早期版本(崩溃)然后进行项目更改(没有崩溃!)来确认这一点。
这是设置:
Project Properties > C/C++ > Optimization > Whole Program Optimization
将其设置为Yes (/GL)
,我的程序就会崩溃。将其更改为 No
即可正常工作。 /GL
开关有什么作用以及为什么会导致此崩溃?
更新2
@Acorn 的出色回答和 @RaymondChen 的评论,提供了追踪并解决问题的线索。有两个问题(都是程序员错误)。
问题1
整个程序优化(wPO)的假设是MSVC编译器正在编译“整个程序”。对于我的 DLL 项目来说,这是一个错误的假设,该项目内部使用第 3 方库,然后由用 Delphi 编写的外部应用程序使用。默认情况下,此设置设置为是 (/GL)
,但应为否
。这感觉像是 Visual Studio 中的一个错误,但无论如何,程序员需要意识到这一点。我不知道 WPO
的用途的所有细节,但至少对于要被其他应用程序使用的 DLL,应该更改默认值。
问题2
严重的程序员错误。这是对第 3 方库的调用,该库返回一个 128 字节的 ASCII 代码,这就是错误:
// Before
// m_config::acSerial defined as "char acSerial[21]"
(void) m_pLib->GetPara(XPARA_PRODUCT_INFO, &m_config.acSerial[0]);
EnterCriticalSection(&crit); // Crash!
// After
#define SERIAL_LEN 20
// m_config::acSerial defined as "char acSerial[SERIAL_LEN+1]"
//...
char acSerial[128];
(void) m_pLib->GetPara(XPARA_PRODUCT_INFO, &acSerial[0]);
strncpy(m_config.acSerial, acSerial, max(SERIAL_LEN, strlen(acSerial)));
EnterCriticalSection(&crit); // Works!
现在很明显的错误是,第 3 方库没有将设备的序列号复制到我提供的 char*
中...它将 128 个字节复制到我的 char 中*
践踏 acSerial
之后内存中所有连续的内容。之前没有注意到这一点,因为 m_pLib->GetPara(XPARA_PRODUCT_INFO, ...)
是对第 3 方库的第一个调用之一,此时其余的连续数据大部分为 NULL。
问题与CRITICAL_SECTION
无关。我感谢 Acorn 和 RaymondChen ...宇宙的这个角落已经恢复了理智。
最佳答案
如果您的程序在 WPO(一种假设您正在编译的内容是整个程序的优化)下崩溃,则意味着该假设不正确,或者优化器最终利用了一些以前没有的未定义行为(没有即使假设是正确的。
一般来说,除非您确实确定自己满足他们的要求,否则请避免启用优化。
为了进一步分析,请提供MRE .
关于c++ - InitializeCriticalSection 在一个项目中有效,但在另一个项目中失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61644823/