![]() |
Absturz beim Beenden wenn Thread ausgeführt wurde
Hi,
ich habe ein Programm, dass per Thread ein ShellExecuteExW ausführt. Starte ich nun mein Programm und erzeuge keinen Thread und beende es wieder gibt es keine Fehlermeldung. Starte ich aber das Programm und erzeuge einen ShellExecuteExW Thread um z.B. den Internet Explorer zu starten kommt es zu einer Fehlermeldung beim Beenden des Programmes. Der Thread wird so erzeugt:
Delphi-Quellcode:
Der Thread beendet sich somit nach dem Starten selbst.
//aufruf im Programm:
TRunProcess.create( ProgramLocation, ProgramParameter, Show, False); //der Thread selber: procedure TRunProcess.Execute; begin { Thread-Code hier einfügen } //add to Semaphore list WaitForSingleObject(Semaphore, INFINITE); ExecAndWait; //remove from Semaphore list ReleaseSemaphore(Semaphore, 1, nil); end; //-------- create (public) --------------------------------------------- constructor TRunProcess.create(Filename, Params: String; WindowState: Word = SW_SHOWNORMAL; Wait : Boolean = False); begin inherited create(True); // CreateSuspended = true freeOnTerminate := true; fApp := Filename; fParam := Params; fWindowState := WindowState; fWait := Wait; fStarted := False; fTimeout := False; Resume; end; Jedoch bekomme ich mit Madexept diese Meldung: Zitat:
|
Re: Problem mit Thread
Ob es daran liegt, weis ich nicht, aber ExecAndWait (von Torry) verwendet "Application.Processmessages" in der Warteschleife. Die ist in deinem Thread nicht nur überflüssig, sondern auch gefährlich und kann zu unerklärlichen Fehlern führen. --> Nimm es raus (Man sollte auf den Process eh anders warten ->WaitForSingleObject)
|
Re: Problem mit Thread
Danke für den Tipp mit ExecAndWait!
Ich habe nun rausgefunden das es so keine Fehlermeldung gibt:
Delphi-Quellcode:
Das ShExecInfoW.fMask habe ich auf 0 gesetzt, da ich nur Prozesse starten will, aber nicht überprüfen ob sie auch wirklich gestartet wurden. Auch benutze ich das Wait nicht!
procedure TRunProcess.ExecAndWait;
var {$IFDEF UNICODE} ShExecInfoW: SHELLEXECUTEINFOW; {$ENDIF} ShExecInfoA: SHELLEXECUTEINFOA; // MSDN: ShellExecuteEx, ShellExecuteInfo begin if (fApp = '') or not FileExists(fApp) then exit; {$IFDEF UNICODE} if Win32IsUnicode = VER_PLATFORM_WIN32_NT then begin ZeroMemory(@ShExecInfoW, SizeOf(ShExecInfoW)); ShExecInfoW.Wnd := GetForegroundWindow; ShExecInfoW.cbSize := SizeOf(SHELLEXECUTEINFOW); ShExecInfoW.fMask := 0; //SEE_MASK_NOCLOSEPROCESS; ShExecInfoW.lpVerb := 'open'; ShExecInfoW.lpFile := PWideChar(WideString(fApp)); ShExecInfoW.lpParameters := PWideChar(WideString(fParam)); ShExecInfoW.lpDirectory := PWideChar(WideString(ExtractFileDir(fApp))); ShExecInfoW.nShow := fWindowState; try ShellAPI.ShellExecuteExW(@ShExecInfoW); if fWait then WaitForSingleObject(ShExecInfoW.hProcess, INFINITE); finally fStarted := ShExecInfoW.hProcess <> 0; end; end else {$ENDIF} begin ZeroMemory(@ShExecInfoA, SizeOf(ShExecInfoA)); ShExecInfoA.Wnd := GetForegroundWindow; ShExecInfoA.cbSize := sizeof(SHELLEXECUTEINFOA); ShExecInfoA.fMask := 0; //SEE_MASK_NOCLOSEPROCESS; ShExecInfoA.lpVerb := 'open'; ShExecInfoA.lpFile := PAnsiChar(AnsiString(fApp)); ShExecInfoA.lpParameters := PAnsiChar(AnsiString(fParam)); ShExecInfoA.lpDirectory := PAnsiChar(AnsiString(ExtractFileDir(fApp))); ShExecInfoA.nShow := fWindowState; try ShellExecuteExA(@ShExecInfoA); if fWait then WaitForSingleObject(ShExecInfoA.hProcess, INFINITE); finally fStarted := ShExecInfoA.hProcess <> 0; end; end; end; Der Fehler beim beenden ist hiervon gekommen:
Delphi-Quellcode:
Ich wollte auf diese Weise den String in ein PWideChar umwandeln.
fDummyPWideChar := '';
GetMem(fDummyPWideChar, Length(fApp) * 2 + 2); ZeroMemory(fDummyPWideChar, Length(fApp) * 2 + 2); ShExecInfoW.lpFile := StringToWideChar(fApp, fDummyPWideChar, Length(fApp) * 2 + 2); FreeMem(fDummyPWideChar); GetMem(fDummyPWideChar, Length(fParam) * 2 + 2); ZeroMemory(fDummyPWideChar, Length(fApp) * 2 + 2); ShExecInfoW.lpParameters := StringToWideChar(fParam, fDummyPWideChar, Length(fParam) * 2 + 2); FreeMem(fDummyPWideChar); GetMem(fDummyPWideChar, Length(ExtractFileDir(fApp)) * 2 + 2); ZeroMemory(fDummyPWideChar, Length(fApp) * 2 + 2); ShExecInfoW.lpDirectory := StringToWideChar(ExtractFileDir(fApp), fDummyPWideChar, Length(ExtractFileDir(fApp)) * 2 + 2); FreeMem(fDummyPWideChar); Hin und wieder hatte ich Probleme beim Starten von Programmen und ich bin mir nicht sicher ob diese Methode:
Delphi-Quellcode:
String -> PWideChar Umwandlung
ShExecInfoW.lpFile := PWideChar(WideString(fApp));
So ganz in Ordnung ist! |
Re: Problem mit Thread
@schwa226: kannst du deinem Thema bitte einen aussagekräftigen Titel geben. Das es um ein Problem geht sagt bereits die gewählte Forenrubrik aus. Und dann bleibt nur noch "Thread" übrig und das kann so ziemlich alles sein. Wenn du einen aussagekräftigen Titel wählst hat dies den Vorteil das andere mit gleichem Problem das ganze später über die Suchfunktion finden können. Für dich hat ein aussagekräftiger Titel den Vorteil das andere die welche die Lösung kennen sofort am Titel sehen "hey das Problem kenn ich da kann ich helfen". Mit einem weniger aussagekräftigen Titel hingegen wird das Thema von vielen schnell überlesen. :)
|
Re: Absturz beim Beenden wenn Thread ausgeführt wurde
Allgemein gilt, das Threads, die mit dem Attribut 'FreeOnTerminate' erzeugt werden, unbedingt *VOR* Beenden der Applikation terminieren müssen. Der Grund ist einfach: Der Destruktor des Threads verwendet globale Variablen der Unit 'Classes', die beim Beenden der Applikation ihrerseits freigegeben werden und somit u.U. beim Beenden des Threads keine Gültigkeit mehr besitzen.
|
Re: Absturz beim Beenden wenn Thread ausgeführt wurde
Danke für den Tipp mit dem FreeOnTerminate!
Nun habe ich noch ein weiteres kleines Problem beim beenden meiner TestApp. Bei meiner VMWare gibt es keine Probleme, bei meinem echten PC bekomme ich aber folgenden madexcept Report:
Code:
Alle Threads die mit FreeOnTerminate = True ausgeführt werden sind beendet und somit auch nicht im Report.
compiled with : Delphi 2009
madExcept version : 3.0k callstack crc : $03ba442a, $fc0a2d5f, $fc0a2d5f exception number : 1 exception class : EInvalidPointer exception message : Ungültige Zeigeroperation. main thread ($15c4): 00404229 +011 MyTestApp.exe System 375 +0 TObject.FreeInstance 0040479a +002 MyTestApp.exe System 375 +0 @ClassDestroy 0040425d +009 MyTestApp.exe System 375 +0 TObject.Destroy 0040426c +008 MyTestApp.exe System 375 +0 TObject.Free 005851bb +11f MyTestApp.exe acSBUtils 1137 +21 UninitializeACScroll 0058a566 +04e MyTestApp.exe acSBUtils 2915 +7 TacScrollWnd.acWndProc 005905d5 +035 MyTestApp.exe acSBUtils 4483 +2 TacBaseWnd.acWndProc 0058accb +02f MyTestApp.exe acSBUtils 3055 +8 TacEditWnd.acWndProc 004d5b2c +02c MyTestApp.exe Controls TWinControl.MainWndProc 0047c1d4 +014 MyTestApp.exe Classes StdWndProc 76eb642b +02b ntdll.dll KiUserCallbackDispatcher 759fd5f9 +00a USER32.dll DestroyWindow 004d54dc +028 MyTestApp.exe Controls TWinControl.DestroyWindowHandle 004ebc97 +033 MyTestApp.exe Forms TCustomForm.DestroyWindowHandle 004e885b +073 MyTestApp.exe Forms TCustomForm.Destroy 0047b3cf +047 MyTestApp.exe Classes TComponent.DestroyComponents 004e6a6d +035 MyTestApp.exe Forms DoneApplication 0045b646 +026 MyTestApp.exe SysUtils DoExitProc 004053dd +021 MyTestApp.exe System 375 +0 @Halt0 005e6c10 +7c8 MyTestApp.exe MyTestApp 228 +183 initialization 75561172 +010 kernel32.dll BaseThreadInitThunk thread $11c0: 76eb5e4a +0a ntdll.dll NtWaitForMultipleObjects 75561172 +10 kernel32.dll BaseThreadInitThunk thread $ec0: 76eb5e7a +0a ntdll.dll NtWaitForWorkViaWorkerFactory 75561172 +10 kernel32.dll BaseThreadInitThunk thread $17bc: 76eb5e7a +0a ntdll.dll NtWaitForWorkViaWorkerFactory 75561172 +10 kernel32.dll BaseThreadInitThunk thread $16a8: 76eb5e7a +0a ntdll.dll NtWaitForWorkViaWorkerFactory 75561172 +10 kernel32.dll BaseThreadInitThunk thread $b0: 76eb4c1a +0a ntdll.dll NtDelayExecution 75241870 +4f KERNELBASE.dll SleepEx 75241813 +0a KERNELBASE.dll Sleep 0045573d +0d MyTestApp.exe madExcept CallThreadProcSafe 004557a7 +37 MyTestApp.exe madExcept ThreadExceptFrame 75561172 +10 kernel32.dll BaseThreadInitThunk >> created by thread $16c4 at: 76c9642e +00 ole32.dll thread $173c: <priority:15> 75a08fbd +26 USER32.dll GetMessageW 0045573d +0d MyTestApp.exe madExcept CallThreadProcSafe 004557a7 +37 MyTestApp.exe madExcept ThreadExceptFrame 75561172 +10 kernel32.dll BaseThreadInitThunk >> created by thread $630 at: 7560480b +00 SHLWAPI.dll thread $1778: 76eb5e7a +0a ntdll.dll NtWaitForWorkViaWorkerFactory 75561172 +10 kernel32.dll BaseThreadInitThunk thread $e94: 76eb5e7a +0a ntdll.dll NtWaitForWorkViaWorkerFactory 75561172 +10 kernel32.dll BaseThreadInitThunk thread $95c: 76eb5e6a +0a ntdll.dll NtWaitForSingleObject 75241796 +66 KERNELBASE.dll WaitForSingleObjectEx 7555effe +3e kernel32.dll WaitForSingleObjectEx 7555efad +0d kernel32.dll WaitForSingleObject 0045573d +0d MyTestApp.exe madExcept CallThreadProcSafe 004557a7 +37 MyTestApp.exe madExcept ThreadExceptFrame 75561172 +10 kernel32.dll BaseThreadInitThunk >> created by thread $838 at: 76c9642e +00 ole32.dll thread $1010: 76eb5e7a +0a ntdll.dll NtWaitForWorkViaWorkerFactory 75561172 +10 kernel32.dll BaseThreadInitThunk thread $2d0: 76eb5d6a +0a ntdll.dll NtTraceControl 76e8e9bb +3c ntdll.dll EtwpNotificationThread 75561172 +10 kernel32.dll BaseThreadInitThunk disassembling: 00404218 public System.TObject.FreeInstance: ; function entry point 00404218 375 push ebx 00404219 mov ebx, eax 0040421b mov eax, ebx 0040421d call +$a6 ($4042c8) ; System.TObject.CleanupInstance 00404222 mov eax, ebx 00404224 call -$11a1 ($403088) ; System.@FreeMem 00404229 > pop ebx 0040422a ret Es wird irgenwo ein Speicher zweimal freigegeben. Jdeoch komme ich nicht darauf wo ich ansetzen soll!? Kann mir da jemand einen Tipp geben? Danke! |
Re: Absturz beim Beenden wenn Thread ausgeführt wurde
Besorg Dir FastMM (kostnix), wusel dich durch die Einstellungen (eine INC-Datei) und -wupps- wird dir der Fehler mit Zeilennummer angezeigt.
|
Re: Absturz beim Beenden wenn Thread ausgeführt wurde
Danke für den Tipp!
Werd's einmal probieren. |
Re: Absturz beim Beenden wenn Thread ausgeführt wurde
Super! Mit FastMM habe ich es gefunden!
Ich habe einen Thread aus einem Dynamischen Array Werte übergeben. Danach habe ich den Eintrag im Array gelöscht. Der Thread wollte das dann aber auch zugreifen und der Eintrag war nicht mehr da... Jetzt mache ich die Übergabe per Copy und es gibt keine Fehler mehr! Danke! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:45 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz