Необработанное исключение/место записи нарушения доступа в примере мьютекса

StackOverflow https://stackoverflow.com/questions/5979866

Вопрос

Я работаю над примером защиты глобального двойника с помощью мьютексов, однако получаю ошибку:

Незаверное исключение в 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, поскольку ошибка повторяется, когда я их добавляю.

Это было полезно?

Решение

Оставшаяся ошибка в вашем коде связана с вызовом WaitForMultipleObjects().Вы устанавливаете третий параметр на 0 (FALSE) так, что основной поток разблокируется, как только любой из 10 потоков завершается.

Это приводит к вызову DeleteCriticalSection() выполняться до завершения всех потоков, создавая нарушение прав доступа, когда один из (возможно) 9 других потоков запускается и вызывает EnterCriticalSection().

Другие советы

Вы пишете за пределами своего threads[10] множество:

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

threads есть только размер 10!

Your problem is that WaitForMultipleObjects is not waiting for all the threads to complete, causing the critical section to be prematurely deleted. According to MSDN, the third argument is

bWaitAll [in]

If this parameter is TRUE, the function returns when the state of all objects in the >lpHandles array is signaled. If FALSE, the function returns when the state of any one of >the objects is set to signaled. In the latter case, the return value indicates the object >whose state caused the function to return.

You set this to 0, which returns when ANY ONE of your threads completes. This causes the following DeleteCriticalSection to be run while there's still threads waiting to access it.

You should also declare score as a volatile so you don't have cached value problem.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top