_beginthreadex Error



  • TheCaleb schrieb:

    ... nur es ist komisch, da es bei mehreren Threads, die ich aus einem Thread starte weiterhin zu dieser Meldung kommt.
    Wenn es nur ~5 sind, dann geht das, bei mehr zickt er.

    Kann es sein, dass ich die Threads immernoch falsch aufrufe??

    _beginthreadex(NULL,4069, Warten,this, 0, &ThreadID)
    

    Bzw ich rufe aus einem Therad mehrere andere auf (max 10) und diese rufen wiederum 1 Thread auf.

    Meinst Du nicht auch, dass 4069 Bytes für den Stack etwas arg wenig sind?

    _beginthreadex(NULL,0, Warten,this, 0, &ThreadID)
    


  • Mag sein, ich habe nur keine Ahnung woe groß der Stack sein sollte!

    Auf jeden Fall tritt bei

    _beginthreadex(NULL,0, Warten,this, 0, &ThreadID
    

    ständig der Fehler ENOMEM auf, wenn ich halt alle Threads starten lasse.
    Wenn ich die Zahl auf der Threads auf 2 minimiere(wo ja sonst auch immer der Fehler auftrat), die der erste Thread aufruft, dann klappt das, sonst tritt halt dieser Fehler auf.

    Was soll ich nu machen?

    Kann das an den Compilereinstellungen liegen oder muss ich voher irgendeine Funktion ausführen oder muss ich die Threads anders aufrufen??



  • Dann vermute ich, dass mindestens einer Deiner Threads Unmengen an lokalem Speicher verwendet (z.B. char szTest[100000]). Diesen Speicher solltest Du dynamisch anlegen.



  • Ich lege ansich die meisten Variabeln dynamisch an, bzw eine Unmenge lege ich auch nicht an!
    Es muss an irgendwas anderes liegen!



  • Dann poste halt mal ein Minimalbeispiel, welches das Problem reproduziert. Haben keine Lust hier rumzuraten, was du in deinem Code treibst!



  • Debugge doch einfach mal rein bis zu CreateThread und schau Dir den "richtigen" Fehlercode an!!!!!!



  • Kann es sein, dass man ein Thread mit

    _beginthreadex(NULL,0, Warten,this, 0, &ThreadID);
    

    nicht öfters in kurzer Zeit nach einander erstellen darf/kann?

    Ich habe mein Programm nochmal völlig umgeschrieben und mir ist aufgefallen, dass wenn ich ein paar Millisekunden warte, dann klappt das!
    Woran kann das liegen?

    Ich starte jetzt auch nur noch max 5 Threads!



  • Ähhh... habe ich mich nicht deutlich ausgedrückt?
    Reindebuggen?

    PS: Und wenn Du Threads in "ms" Abstand erstellst ist mir klar, das Du Probleme bekommst... Du kannst nur eine bestimmte (kleine) Anzahl an Threads pro Prozess erstellen!



  • Jochen Kalmbach schrieb:

    Du kannst nur eine bestimmte (kleine) Anzahl an Threads pro Prozess erstellen!

    Wie klein kann denn die Anzahl sein?
    Ich habe mal gelesen, dass man so ca. 1000 Threads erzeugen kann.
    Denn ich merke gerade, dass bei dem 5. Thread, den ich starten möchte, der Fehler auftritt!
    Ich ereuge diese Thrads direkt nacheiandner in dem Hauptprozess (TForm1).
    Kann ich das irgendwie umgehen oder hinbekommen, dass ich mehr als nur 4 Thrads starten kann?



  • Kannst Du den Fehler nachvollziehen?
    Auch im Debugger?
    (Ich sage es zum letzten Mal): Debugge in die _beginthrtead... Funktion rein

    Wenn Du es beim Debuggen nicht Nachvollziehen kannst, dann setzte in _beginthread.. einen Breakpoint, wo der Fehler festgestellt wird.

    So findest Du sofort die *genaue* Ursache!



  • Beim Debuggen tritt kein anderer Fehler auf!
    Ich sehe diesen Fehler ja nur, da ich ihn so abfrage:

    if(!_beginthreadex(NULL,stackgroesse, Bearbeiten,this,0, &ThreadID))
        Form1->Erroraus("Bearbeiten",errno);
    ...
    
    void __fastcall TForm1::Erroraus(AnsiString Meldung,unsigned int Err)
    {
    	AnsiString tmp;
    	if(Err==ENOMEM)
    	{
    		tmp="ENOMEM";
    	}
    	else if(Err==EAGAIN)
    	{
    		tmp="EAGAIN";
    	}
    	else if(Err==EINVAL)
    	{
    		tmp="EINVAL";
    	}
    	MessageBox(NULL,tmp.c_str(),("Error:"+Meldung).c_str() , MB_OK);
    }
    

    Achso: Komischer Weise tritt der Fehler jetzt erst bei dem 6. Aufruf (mehr wollte ich auch nicht erzeugen) auf, obwohl ich nichts geändert haben!



  • if(!_beginthreadex(NULL,stackgroesse, Bearbeiten,this,0, &ThreadID)) 
    {
        DWORD dwLastError = GetLastError();
        Form1->Erroraus("Bearbeiten",errno); 
    }
    

    Und was sagt GetLastError an dieser Stelle?



  • Naja, das ist nicht unbedingt zielführend, da Du weisst ja nicht, was in "_beginthread" sonst noch alles gemacht wird!

    Einfacher ist: Ersetze "_beginthread" durch "CreateThread" und rufe dann GetLastError, auf, wenn es schief ging!!!



  • Jochen Kalmbach schrieb:

    Naja, das ist nicht unbedingt zielführend, da Du weisst ja nicht, was in "_beginthread" sonst noch alles gemacht wird!

    Einfacher ist: Ersetze "_beginthread" durch "CreateThread" und rufe dann GetLastError, auf, wenn es schief ging!!!

    _beginthreadex allokiert TLS-Speicher für die CRT-Datenstrukturen und ruft dann CreateThread auf. Im Fehlerfall wird der Speicher wieder freigegeben. Mehr passiert da nicht.



  • Er verwendet die Borland-CRT... ich hab sie halt nicht hier und müsste raten, was Borland da macht...



  • Also was soll ich nun machen?
    Diese Fehlermeldung ist ja eine von dem Errorcodesatz von GetLastError, nur dass der in errno drin steht!
    Also soll ich nu mal CreateThread antesten??
    Denn mit dieser Funktion habe ich noch keine Erfahrungen!



  • Probiere doch erst einmal meinen Vorschlag. Wenn GetLastError nichts Vernünftiges ausgibt, dann machst Du es wie Jochen es vorgeschlagen hat.



  • GetLastError() gibt bei CreateThread den Fehler 8 raus:

    8
    ERROR_NOT_ENOUGH_MEMORY
    Not enough storage is available to process this command.



  • Tja, dann liegt es wohl am fehlenden Speicher (vermutlich dem Stack).

    Ich würde jetzt alles in den Threadfunktionen auskommentieren und nacheinander wieder freigeben, um den Verursacher zu finden.



  • Wie viel Speicher benützt denn Deine Applikation?

    Ein Programm kannn z.B. Memory-Fragmentierung sein. Lass es mal unter WinDbg laufen und rufe mal

    !address -summary
    

    auf.


Anmelden zum Antworten