Speicherverletzung bei Verwendung von EnterCriticalSection



  • Momentan komme ich wirklich nur schrittweise voran ..
    Ich habe einen Winsocket-Server, welcher auf einkommende Nachrichten wartet. Dieser läuft in einem eigenen Thread, damit der Ursprungsthread per polling über eine gemeinsame Variable auf die empfangenen Nachrichten zugreifen kann. Aufs wichtigste reduziert sieht das ungefähr so aus:

    basic_server.h: Hier wird die von main und basic_server.cpp gemeinsam benutzte CRITICAL_SECTION Variable deklariert

    extern CRITICAL_SECTION Section;
    

    main.cpp: Hier wird der server-Thread gestartet, nachdem die CRITICAL_SECTION Variable initialisiert worden ist und eine Endlosschleife gibt den gemeinsamen Puffer für die angekommene Nachricht aus:

    InitializeCriticalSection(&Section);
    
    HANDLE thread = (HANDLE)_beginthread(startServer, 0, &params);
    
    cout << "thread started; handle: "<< thread << endl;
    
    while(1)
    {
       cout << strlen(getExpression()) << endl;
       Sleep(500);
    }
    
    DeleteCriticalSection(&Section);
    

    basic_server.cpp: Hier ist die CRITICAL_SECTION Variable Section deklariert und die Nachrichten werden eingelesen, welche dann in die synchronisierte Puffervariable receivedString geschrieben.
    Die Initialisierung der CRITICAL_SECTION geschieht also in der main() während in basic_server.cpp die kritischen Bereiche gesichert werden

    char receivedString[1024];
    CRITICAL_SECTION Section;
    
    char* getExpression()
    {
    	EnterCriticalSection(&Section);
    	return receivedString;
    	LeaveCriticalSection(&Section);
    }
    
    bool echoIncomingPackets(SOCKET sd)
    {
        // Read data from client
        char acReadBuffer[kBufferSize];
        int numReadBytes;
    
    	InitializeCriticalSection(&Section);
    
    	do 
    	{
    		cout << "entering critical section" << endl;
    		// !!
    		EnterCriticalSection(&Section); // HIER FEHLER!!
    
    		cout << "after CS" << endl;
    
            numReadBytes = recv(sd, acReadBuffer, kBufferSize, 0);
    
    		if (numReadBytes > 0) 
    		{
                cout << "Received " << numReadBytes <<
                        " bytes from client." << endl;
    
    			acReadBuffer[numReadBytes] = '\0';
    
    			strcpy(receivedString, acReadBuffer);
    
    			cout << "acReadBuffer  : " << acReadBuffer << endl;
    			cout << "receivedString: " << receivedString << endl << endl;
    
            }
            else if (numReadBytes == SOCKET_ERROR) 
    		{
                return false;
            }
    
    		// !!
    		LeaveCriticalSection(&Section);
    
        } while (numReadBytes != 0);
    
        cout << "Connection closed by peer." << endl;
        return true;
    }
    

    In der Zeile

    EnterCriticalSection(&Section);
    

    geschieht die Speicherverletzung. Ich habe bei einem Test bemerkt, dass wenn die CriticalSection in der gleichen Methode auch initialisiert wird alles funktioniert. In der MSDN steht, die Initialisierung müsse nur von irgendeinem Thread des gleichen Prozesses vorgenommen werden. Daher verstehe ich den Fehler nicht, denn das habe ich gemacht (in main()).



  • (1) Du machst 2x InitializeCriticalSection
    (2) Wenn ein Fehler auftritt, vergißt du das LeaveCriticalSection. (Abhilfe: Imemr dran denken und nie mit exceptions arbeiten, AutoLock - Klasse oder ScopeGuard)



  • peterchen schrieb:

    und nie mit exceptions arbeiten

    Wieso das denn nicht?



  • Bitte Context beachten ("Immer dran denken und nie mit exceptions arbeiten")
    Folgender fall:

    void foo()
    {
       EnterCriticalSection(&cs);
    
       bool ok = lalala();
       if (!ok)
       {
         LeaveCriticalSection(&cs);
         return ErrorLalalaDoesntWork;
       }
       lululu();
       LeaveCriticalSection(&cs);
    }
    

    Hier wird die CS nicht freigegeben, wenn im geschützten Rump eine esception fliegt.



  • peterchen schrieb:

    Bitte Context beachten ("Immer dran denken und nie mit exceptions arbeiten")
    Folgender fall:

    void foo()
    {
       EnterCriticalSection(&cs);
    
       bool ok = lalala();
       if (!ok)
       {
         LeaveCriticalSection(&cs);
         return ErrorLalalaDoesntWork;
       }
       lululu();
       LeaveCriticalSection(&cs);
    }
    

    Hier wird die CS nicht freigegeben, wenn im geschützten Rump eine esception fliegt.

    Da würde ich jetzt nen Autolock-Klasse nehmen und trotzdem mit exceptions arbeiten, denn die sind doch ne prima Sache, oder nicht?



  • ja mein' ich doch 🙂


Anmelden zum Antworten