【问题标题】:Unhandled exception / Access violation writing location in a Mutex exampleMutex 示例中未处理的异常/访问冲突写入位置
【发布时间】:2011-08-24 04:55:24
【问题描述】:

我正在研究一个使用互斥锁保护全局双精度的示例,但是我得到了错误 -

在 0x77b6308e 处未处理的异常 Lab7.exe: 0xC0000005: 访问冲突 写入位置 0x00000068。

我认为这与访问分数有关? (全局双)

#include <windows.h>
#include <iostream>   
#include <process.h>

double score = 0.0; 


HANDLE threads[10];     

CRITICAL_SECTION score_mutex; 


unsigned int __stdcall MyThread(void *data)
{
    EnterCriticalSection(&score_mutex);
    score = score + 1.0; 
    LeaveCriticalSection(&score_mutex); 

    return 0;
}

int main()
{
    InitializeCriticalSection(&score_mutex); 

    for (int loop = 0; loop < 10; loop++)
    {

        threads[loop] = (HANDLE) _beginthreadex(NULL, 0, MyThread, NULL, 0, NULL); 
    }

    WaitForMultipleObjects(10, threads, 0, INFINITE); 

    DeleteCriticalSection(&score_mutex); 

    std::cout << score; 

    while(true);

}

更新:

修复了将循环设置为 1000 而不是 10 的问题后,错误仍然发生,但是当我注释掉引用互斥锁的代码时,错误没有发生。

CRITICAL_SECTION score_mutex; 
EnterCriticalSection(&score_mutex); 
LeaveCriticalSection(&score_mutex); 
InitializeCriticalSection(&score_mutex); 
DeleteCriticalSection(&score_mutex); 

更新 2

线程按照惯例返回 0(这是漫长的一周!)

我尝试重新添加与互斥锁相关的代码,并且程序将在 CRITICAL_SECTION、InitializeCriticalSection 和 DeleteCriticalSection 全部重新添加的情况下编译并运行良好(当然,除了双精度的竞争条件问题)。问题似乎是与 EnterCriticalSection 或 LeaveCriticalSection 一起使用,因为当我添加它们时错误再次发生。

【问题讨论】:

  • 注意:按照惯例,如果线程没有错误终止,则返回代码为0。
  • 您是否检查过任何调用函数的返回值? 始终检查 C API 函数的错误代码。这是您应该采取的第一步,尤其是当您发生崩溃时!
  • 谢谢你 - 我应该想到的 - 这是漫长的一周!
  • 找到你的错误,看看我的答案。
  • @ShimmerGeek:最后你不需要一个繁忙的循环while(true);WaitForMultipleObjects 等待所有辅助线程,使主线程不退出。

标签: c++ multithreading winapi critical-section waitformultipleobjects


【解决方案1】:

您代码中的剩余错误在于对WaitForMultipleObjects() 的调用。您将第三个参数设置为 0 (FALSE),这样主线程就会在 10 个线程中的任何个线程完成后立即解除阻塞。

这会导致在所有线程完成之前执行对DeleteCriticalSection() 的调用,从而在(可能)9 个其他线程之一启动并调用EnterCriticalSection() 时创建访问冲突。

【讨论】:

  • 哦,诅咒,我实际上已经产生了一个不同的错误,并将其设置为 TRUE(在不同的示例中),然后很快就忘记了!非常感谢:)
  • 有了这个答案,很高兴知道调用 DeleteCriticalSection() 会导致 EnterCriticalSection() 的另一个线程上的访问冲突。这当然很容易理解,但如果首先出现访问冲突,可能不会。
【解决方案2】:

您的写入超出了threads[10] 数组的末尾:

for (int loop = 0; loop < 1000; loop++){
     threads[loop];
}

threads 的大小只有 10!

【讨论】:

  • 这到底是怎么回事...哇,好的,已经解决了!虽然仍然收到错误:)
  • 我认为你也需要初始化你的临界区对象:score_mutexInitializeCriticalSection
  • 哦,错过了。现在一切看起来都没有问题。如果在调试器中运行,错误发生在哪一行?
【解决方案3】:

您的问题是 WaitForMultipleObjects 没有等待所有线程完成,导致临界区被过早删除。根据MSDN,第三个参数是

bWaitAll [输入]

如果此参数为 TRUE,则函数会在 >lpHandles 数组中的所有对象的状态发出信号时返回。如果为 FALSE,则当任何一个对象的状态设置为已发出信号时,该函数将返回。在后一种情况下,返回值表示>其状态导致函数返回的对象。

您将此设置为 0,当您的任何一个线程完成时返回。这会导致以下 DeleteCriticalSection 在仍有线程等待访问它时运行。

【讨论】:

  • 是的,愚蠢的错误 - 现在已修复,谢谢。但是仍然发生错误。
【解决方案4】:

您还应该将 score 声明为 volatile,这样就不会出现缓存值问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-26
    • 2013-01-23
    • 2019-03-16
    • 2013-08-22
    相关资源
    最近更新 更多