AccessViolation in hausgemachter Threadklasse
-
Hi zusammen,
im Moment habe ich ds Problem, dass aus einem firmeneigenen ( mittlerweile nicht mehr benutzen Klasse ) Tool, eine städnig auftretende AccessViolation rauszusuchen und zu beheben..
nach mehrfachem Tracking mit AQTime5 und setzen von tausenden CriticalSections und auskommentierung von Tonnen von Sourcecode, bin ich mittlerweile der überzeugung, dass der fehler irgendwo tief drin sitzen muss... die vermutung liegt dabei im moment auf der selbstgebackenen threadklasse... vielleicht findet ja jemand was..
danke
#include <sysutils.hpp> #pragma hdrstop #include <thread.h> #include <util.h> #include <kernel.h> #include <process.h> #include <typeinfo.h> #include "klog.h" //------------------------------------------------------------------------------ // namespace kernel //------------------------------------------------------------------------------ namespace kernel { //------------------------------------------------------------------------------ // constants //------------------------------------------------------------------------------ const size_t MAX_THREAD_QUEUE_SIZE= 64; //------------------------------------------------------------------------------ // global variables //------------------------------------------------------------------------------ static critical_section Thread_Synch; static CThread* Thread_StartQueue[MAX_THREAD_QUEUE_SIZE]; static size_t Thread_StartQueueSize= 0; static unsigned long Thread_Instance = 0; //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ bool __thread_queue_thread(CThread* thread) { if (Thread_StartQueueSize<MAX_THREAD_QUEUE_SIZE) { Thread_StartQueue[Thread_StartQueueSize++]= thread; return true; } else return false; } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ void __thread_start_queued_threads() { for (size_t i= 0; i<Thread_StartQueueSize; ++i) if (Thread_StartQueue[i]->GetThreadState()==thrdInactive) Thread_StartQueue[i]->Start(); Thread_StartQueueSize= 0; } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ CThread::CThread() : ThreadState(thrdInactive), TerminationSignaled(false), hThread(INVALID_HANDLE_VALUE), ThreadID(0) { blockguard lock(Thread_Synch); Instance= ++Thread_Instance; klog("THREAD", "CThread ctor called (%lu)", Instance); } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ CThread::~CThread() { klog("THREAD", "CThread dtor called (%lu)", Instance); } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ DWORD CThread::GetID() const { return ThreadID; } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ HANDLE CThread::GetHandle() const { return hThread; } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ EThreadState CThread::GetThreadState() const { //blockguard lock(thread_synch); return ThreadState; } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ bool CThread::IsTerminated() const { return GetThreadState()==thrdTerminated; } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ bool CThread::IsSignaled() const { //blockguard lock(thread_synch); return TerminationSignaled; } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ bool CThread::Start(EThreadPriority priority) { //blockguard lock(thread_synch); if (ThreadState!=thrdInactive && ThreadState!=thrdTerminated) return false; else { if (hThread!=INVALID_HANDLE_VALUE) CloseHandle(hThread); TerminationSignaled= false; ThreadState = thrdActive; hThread= (HANDLE) _beginthreadNT(&CThread::_thread_thunk, 4096, this, 0, 0, &ThreadID); if (hThread==INVALID_HANDLE_VALUE) { ThreadState= thrdInactive; klog("THREAD", "thread launch failed (%lu)\nOS Error=%s", Instance, oserr_to_str(GetLastError()).c_str()); } else { SetThreadPriority(hThread, priority); klog("THREAD", "thread successfully launched, tid=%lu, priority=%i (%lu)", ThreadID, GetThreadPriority(hThread), Instance); } return hThread!=INVALID_HANDLE_VALUE; } } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ void CThread::Terminate() { blockguard lock(thread_synch); if (ThreadState==thrdInactive) ThreadState= thrdTerminated; TerminationSignaled= true; ReleaseWaitState(); } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ bool CThread::Suspend() { blockguard lock(thread_synch); if (ThreadState==thrdActive && SuspendThread(hThread)!=0xFFFFFFFFUL) { ThreadState= thrdSuspended; return true; } else return false; } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ bool CThread::Resume() { blockguard bg(thread_synch); if (ThreadState==thrdSuspended && ResumeThread(hThread)!=0xFFFFFFFFUL) { ThreadState= thrdActive; return true; } else return false; } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ bool CThread::Kill() { return TerminateThread(hThread, 0); } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ DWORD CThread::SetIdealProcessor(DWORD processor) { return SetThreadIdealProcessor(hThread, processor); } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ DWORD CThread::SetAffinityMask(DWORD affinity_mask) { return SetThreadAffinityMask(hThread, affinity_mask); } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ bool CThread::WaitForTermination(DWORD timeout) { if (GetThreadState()==thrdActive) { klog("THREAD", "waiting for thread termination, tid=%lu (%lu)", ThreadID, Instance); if (WaitForSingleObject(hThread, timeout)==WAIT_OBJECT_0) return true; } return GetThreadState()==thrdTerminated; } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ bool CThread::TerminateAndWait(DWORD timeout) { Terminate(); return WaitForTermination(timeout); } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ EThreadPriority CThread::GetPriority() const { return (EThreadPriority) GetThreadPriority(hThread); } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ bool CThread::SetPriority(EThreadPriority priority) { return SetThreadPriority(hThread, priority); } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ DWORD CThread::GetExitCode() { DWORD exit_code; GetExitCodeThread(hThread, &exit_code); return exit_code; } //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ void CThread::ReleaseWaitState() {} //------------------------------------------------------------------------------ // Function //------------------------------------------------------------------------------ void _USERENTRY CThread::_thread_thunk(void* obj) { FILETIME ft_creation, ft_exit, ft1, ft2; CThread *thread; unsigned long instance; Sleep(5); thread = static_cast<CThread*>(obj); instance= thread->Instance; try { klog("THREAD", "thread starts, tid=%lu (%lu)", GetCurrentThreadId(), instance); thread->Execute(); thread->thread_synch.enter(); thread->ThreadState= thrdTerminated; thread->thread_synch.leave(); GetThreadTimes(GetCurrentThread(), &ft_creation, &ft_exit, &ft1, &ft2); klog("THREAD", "thread terminates (%lu)\nstatistics: created=%s", instance, filetime_to_str(ft_creation).c_str()); } catch (const Exception& e) { GetThreadTimes(GetCurrentThread(), &ft_creation, &ft_exit, &ft1, &ft2); klog( "THREAD", "EXCEPTION detected: '%s' (%lu)\nstatistics: created=%s", e.Message.c_str(), instance, filetime_to_str(ft_creation).c_str()); signal_process_termination(-99); } catch (const std::exception& se) { GetThreadTimes(GetCurrentThread(), &ft_creation, &ft_exit, &ft1, &ft2); klog( "THREAD", "EXCEPTION detected: type '%s' (%lu)\n%s\nstatistics: created=%s", typeid(se).name(), instance, se.what(), filetime_to_str(ft_creation).c_str()); signal_process_termination(-98); } catch (...) { GetThreadTimes( GetCurrentThread(), &ft_creation, &ft_exit, &ft1, &ft2); klog( "THREAD", "EXCEPTION detected: unknown type (%lu)\nstatistics: created=%s", instance, filetime_to_str(ft_creation).c_str()); signal_process_termination(-97); } _endthread(); } } // namespace kernel
-
Warum benutzt du nicht einfach den Debugger?
-
Bei AccessViolations in Kombination mt Threads kannst du mit Borland selber nur den CPU-CallStack "debuggen"... und da nützliche Infos über die Fehlerquelle zu finden ist praktisch unmöglich leider..
-
Unsinn! Scroll mal im Stackwindow das aufgeht (CPU als Titelleiste) nach oben. Und auch wenn du den Callingstack anschaust, dann siehst du da, wo er hergekommen ist (ist ja der Witz am Callingstack) da wird wohl eine Funktion von dir zu finden sein.
Ansonsten schmeiss hald Breakpoints in sämtliche Threadfunktionen und steppe sie einzeln durch, damit du rausfindest wo dass die Exception ausgelöst wird.
-
Sorry, aber kein Unsinn... mit AQTime5 ( Profilertool ) seh ich ja den CallStack, aber der fliegt bei jeder Exception an einer anderen Stelle... dazu muss ich sagen, dass es in diesem fall sehr schwierig ist, immer gleiche Testdaten bereitzustellen...
Deshalb habe ich ja die Vermutung das es der Thread ist.. die einzige Gemeinsamkeit beim CallStack ist halt dass sie nur fliegt, sobald mehr als 1 Thread + WinMain Thread laufen...