【发布时间】:2016-01-03 15:20:01
【问题描述】:
我正在开发一个使用临界区来同步实体数组的多线程应用程序。该数组保存在一个结构中,如下所示。 pe 数组的每个成员都包含自己的criticalSection,在访问该成员之前总是声明它(我已经全部检查过了)。
struct PlayerEntity {
DWORD state;
BOOL onScreen;
DWORD team;
DWORD_PTR baseAddr;
BOOL valid;
CRITICAL_SECTION critSec;
};
struct EntityList {
DWORD count;
PlayerEntity pe[128];
};
EntityList *getStaticEntityList() {
static EntityList entityList;
return &entityList;
}
在启动应用程序后,两个线程之一会在尝试进入临界区时看似随机地抛出异常(如下)。
Exception thrown at 0x00007FFC8813E7C5 (ntdll.dll) in RustExp.exe:
0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
我假设这个错误是由试图访问它们的 DebugInfo 对象的临界区对象引发的,因为每个对象的 DebugInfo 指针在初始化后都指向 0xffffffffffffffff。但是在错误检查之后,它们都指向 0xcdcdcdcdcdcdcdcd。
我试图查找有关关键部分对象及其成员的信息,但我似乎无法在它们上找到任何东西。所以我问,初始化的临界区对象是否应该将其 DebugInfo 指向 0xffffffffffffffff 以及临界区何时尝试访问其 DebugInfo(从而引发读取错误)?
注意:这是在 Windows 10 上运行的。
【问题讨论】:
-
它位于
winnt.h,类似于:typedef struct _RTL_CRITICAL_SECTION { PRTL_CRITICAL_SECTION_DEBUG DebugInfo; LONG LockCount; LONG RecursionCount; HANDLE OwningThread; HANDLE LockSemaphore; ULONG_PTR SpinCount; } RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;。在winbase.h中等同于CRITICAL_SECTION。但用户不应触摸任何字段。InitializeCriticalSection()在使用前你用过吗? -
是的,它们都已初始化。在初始化之前,DebugInfo 指针为 NULL。之后它们都指向 0xffffffffffffffff。我还没有看到其他人描述这种行为,所以我认为这是问题所在。其他字段似乎都很好。
-
是的,我没有想到这一点,但是看着我的代码,我有一个覆盖每个 PlayerEntity 的 critSec 的内存副本。直到我的两个线程在尝试访问同一个 PlayerEntity 时发生冲突时才抛出错误,这就是它随机发生的原因。感谢弗兰基的帮助。 PS:我现在如何结束这个问题?
-
我发布了答案。你可以接受。
标签: c multithreading thread-safety access-violation critical-section