c++ - InitializeCriticalSection 在一个项目中有效,但在另一个项目中失败

标签 c++ critical-section

在 Windows 10 x64 上使用 Visual Studio 2019 Professional。我有几个 C++ DLL 项目,其中一些是多线程的。我使用 CRITICAL_SECTION 对象来保证线程安全。

在 DLL1 中:

CRITICAL_SECTION critDLL1;
InitializeCriticalSection(&critDLL1);

在 DLL2 中:

CRITICAL_SECTION critDLL2;
InitializeCriticalSection(&critDLL2);

当我将 critDLL1 与 EnterCriticalSectionLeaveCriticalSection 一起使用时,在 _DEBUGNDEBUG 模式下一切都很好。但是,当我使用 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/

相关文章:

c++ - Sublime-text3突出显示}为非法字符

c++ - Botan::AutoSeeded_RNG/m128i _mm_shuffle_epi8:目标特定选项不匹配

c++ - 如果我在转换中丢失数据,我可以在 C++ 中引发异常吗?

python - 使用多个进程在 Python 中写入文件

linux - 公平临界区 (Linux)

C++ vector <整数> : add int elements to vector that are even and already in the vector

c++ std::enable_if .... 否则?

c++ - 如何避免在用户模式下抢占我的线程

c++ - 通过继承而非组合锁定

c++ - 在函数和子函数中调用相同的临界区