Programmabsturz



  • Hallo,
    in meinem Programm habe ich einen nichtmodalen Dialog, in dem zyklisch Messwerte dargestellt werden die über RS232 aus einem Gerät gelesen werden.
    Wenn ich nun den Dialog beende, stürtzt mein Programm ab.
    Ich benutze für die Kommunikation keinen eigenen Thread sondern einen Timer und eine Nachrichtenschleife.
    kann mir jemand helfen??
    Hier ist mal ein wenig Code.

    /* nicht modales Fenster */
    void CDisplay::InitialDialog(const CString& strTitle)
    {	
    	UpdateData (FALSE);
    	SetWindowText(strTitle);
    }
    
    CDisplay* CDisplay::Instance(BOOL* bpCancel, CWnd* pParentWnd)
    {
    	BOOL bWOldState=FALSE;
    	ASSERT(bpCancel!=NULL);
    	if (bpCancel==NULL) return NULL;
    	CDisplay* pWDlg = new CDisplay;
    
    	if (pParentWnd==NULL) pWDlg->m_ParentWnd=                      AfxGetApp()-  >m_pMainWnd; // can be NULL!
    	else 
    	{
    		pWDlg->m_pParentWnd = pParentWnd;
    	}
    
    	if (!pWDlg->Create(IDD_VIEW_DISPLAY, pWDlg->m_pParentWnd))
    	{
    		delete pWDlg;
    		pWDlg=NULL;
    		return NULL;
    	}
    	if (pWDlg->m_pParentWnd != NULL)
    	  bWOldState = pWDlg->GetParentWnd()->EnableWindow(FALSE); 
    																	pWDlg->EnableWindow (TRUE);
    	if (bWOldState) pWDlg->m_bOldEnableState=FALSE;
    	else pWDlg->m_bOldEnableState=TRUE;
    
    	pWDlg->m_pbCancel= bpCancel;
    	pWDlg->ShowWindow(SW_SHOW);
    	return pWDlg;
    }
    
    void CDisplay::Done()
    {
    	if (::IsWindow(GetSafeHwnd())) 
    	{		
    		OnCancel();
    	}
    }
    
    void CDisplay::OnCancel()
    {
    	notifyCancel();
    	if (m_pParentWnd!=NULL) GetParentWnd()->EnableWindow(m_bOldEnableState);
    	if (::IsWindow(GetSafeHwnd())) DestroyWindow();
    
    }
    void CDisplay::PostNcDestroy()
    {
    	delete this;
    }
    
    void CDisplay::OnCancelMode()
    {
    	CDialog::OnCancelMode();
    
    void CMainFrame::OnViewDisplay()
    {
    	BOOL bCancel=FALSE;
    	CDisplay* MyDisplay;
    	MSG Msg;
    
    	MyDisplay=CDisplay::Instance (&bCancel, this );
    	MyDisplay->InitialDialog ("Messwertfenster");
    
    	MyDisplay->UpdateData(FALSE);
    
    	CTime StartTime = CTime::GetCurrentTime();
    	CTimeSpan DiffTime;
    	int Seconds = 0;
    
        while (bCancel==FALSE)
    	{	
    		while (Seconds<3)
    		{
    			DiffTime = CTime::GetCurrentTime()- StartTime;
    			Seconds= DiffTime.GetSeconds();
    
    			while (::PeekMessage(&Msg, NULL,0,0,PM_NOREMOVE))
    			{
    			 if (!AfxGetApp()->PumpMessage())                   {::PostQuitMessage  (0); break;}
    
    			}
    		}
    		Seconds=0;
    	// hier werden die Befehle 0x10 und 0x0C herausgegeben 
    	// + Variablen des Fensters geändert 
    
    	   MyDisplay->DisplayCom();
    
    	   MyDisplay->UpdateData(FALSE);
    	}
    	MyDisplay->Done();
    }
    


  • Und hier die Kommunikation.

    void CDisplay::DisplayCom()
    {	
    	BYTE Message0[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0x81, 0x00, 0x00, 0x83};
    	BYTE Message1[7] = {0x20, 0x70, 0x00, 0x00, 0x00, 0x00, 0x90};
    	BYTE Message2[2] = {0x10, 0x01};
    	BYTE Message3[2] = {0x10, 0x02};
    	BYTE Message4[7] = {0x20, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x3E};
    	BYTE Message5[2] = {0x10, 0x0c};
    	BYTE Response[200];
    
    	MyCOM.DC_Com_Properties.BaudRate = 1200;
    	MyCOM.DC_Com_Properties.ByteSize = 8;
    	MyCOM.DC_Com_Properties.Parity = NOPARITY;
    	MyCOM.DC_Com_Properties.StopBits =1;
    	MyCOM.DC_Com_Properties.fOutxCtsFlow=0;
        MyCOM.DC_Com_Properties.fOutxDsrFlow=0;
    
        int Retries= RETRIES_MAX;
    	int ScaleValid=0;     // lower and upper scale values not valid
    
    	if (FirstBytes==0)  
    	{
    		// send command to TH100
    		 FirstBytes=1;
             MyCOM.Open (2);
    		 MyCOM.ControlDTR(true);   // power on  	
    		 Wait_Refresh (1500);
    		 ASSERT (MyCOM.Communication (Message0, 10, Response, 0, 3000));
    		 ASSERT (MyCOM.Communication (Message1, 7,  Response, 2, 3000));
    		 //for(int j=0; j<4; j++)if (Response[j]!=0xE5) ASSERT (0);     /// CHECKEN
    		 MyCOM.ControlDTR(false);   // power off  
    		 Wait_Refresh (1500);
    		 MyCOM.ControlDTR(true);   // power on  
    		 Wait_Refresh (1500);
    
    		 if (MyCOM.Communication (Message2, 2,  Response, 8, 1000))
    		 {
    			 // Wert für upper Value in Response 
    	         fValueScale[0]=GetfValue (0x01,Response);
    			 ScaleValid++;
    	     }
    
    		 if (MyCOM.Communication (Message3, 2,  Response, 8, 1000))
    		 {
    			 // Wert für lower Value in Response 
    			 fValueScale[1]=GetfValue (0x02,Response);
    			 ScaleValid++;
    		 }
    		 ASSERT (MyCOM.Communication (Message4, 7,  Response, 0, 3000));  // Strom auf 4mA setzen
    		 if (ScaleValid==2) SetValueScale();
    		 else
    		 {
              fValueScale[0]=9999; fValueScale[1]=9999; SetValueScale();
    		 }
    	}
    	else
    	{
    	 	// Read cyclic temperature
    		Wait_Refresh(3000);
    		fTemperaturePV = 9999;
    		if (MyCOM.Communication(Message5, 2, Response,8, 3000))   // measure cyclic value
    		   fTemperaturePV= GetfValue (0x0C, Response);
    
    		SetPVTemperature();    	
    
    	}
    }
    


  • Hat denn niemand eine Idee woran das liegen kann?
    Ich nehme an das ein Objekt nicht richtig zerstört wurde, aber welches?


  • Mod

    Meine Kristallkugel steht auf meinem Fensterbrett zu Hause in meinem Arbeitszimmer.

    Verate uns doch mal wo Dein Programm abstürzt?
    Was zeigt der Callstack an? D.h. welche Funktion wird gerade von wem ausgeführt.

    Nur so, kann man schwer was sehen. Gib uns einen Tipp und eine Chance...



  • Also wenn ich den Dialog kurz nachdem er erstellt wurde wieder schließe bekomme ich eine unbehandelte Ausnahme und der CallStack steht in der folgenden Routine:

    inline void* CThreadSlotData::GetThreadValue(int nSlot)
    {
    	EnterCriticalSection(&m_sect);
    	ASSERT(nSlot != 0 && nSlot < m_nMax);
    	ASSERT(m_pSlotData != NULL);
    	ASSERT(m_pSlotData[nSlot].dwFlags & SLOT_USED);
    	ASSERT(m_tlsIndex != (DWORD)-1);
    	if( nSlot <= 0 || nSlot >= m_nMax ) // check for retail builds.
    	{
    		LeaveCriticalSection(&m_sect);
    		return NULL;
    	}
    
    	CThreadData* pData = (CThreadData*)TlsGetValue(m_tlsIndex);
    	if (pData == NULL || nSlot >= pData->nCount)
    	{
    		LeaveCriticalSection(&m_sect);
    		return NULL;
    	}
    	void* pRetVal = pData->pData[nSlot];
    	LeaveCriticalSection(&m_sect);
    	return pRetVal;
    }
    

    Der CallStack steht dann in der letzten Zeile bei return pRetVal.

    Wenn ich mit dem beenden des Dialogs länger warte passiert dies nicht, dann stürtzt mein Programm ohne irgendeine Meldung ab. Ich habe dann mal einen Breakpoint gesetzt und mit F11 weitergesprungen bis ich dann in einen sehr langen Assemblercode kam, dort hab ich dann abgebrochen.
    Ich hoffe das hilft etwas weiter.


  • Mod

    Scheint, so als ob noch irgendetwas auf ein Objekt zugreifen will, das bereits zerstört ist.
    Schau Dir doch mal den Callstack genauer an. Da siehst Du doch wer was tun möchte...



  • Hmmm? Wie kann ich das denn dort sehen??


  • Mod

    Wenn Du das Callstack Fenster hats, wird doch Zeile für Zeile augelistet, wer wen wo aufruft.



  • Ich muss jetzt erstmal rausfinden wie ich das Callstack fenster öffne 😉
    Hatte das bisher noch nicht so benutzt.



  • Ahja die Aufrufliste hab ich jetzt gefunden.
    Wo muss ich nun einen Haltepunkt setzen?
    Und wie sehe ich dort was noch aufgerufen wird?
    Werde nicht schlau aus dem Code.


  • Mod

    Da musst Du keinen Haltepunkt setzen. Wenn es kracht kannst Du hier durch Doppelklick einfach sehen wer wen wann aufruft...

    Wo kracht es nun? Bei einem Destruktor vermute ich mal!



  • Hier zeig ich dir jetzt mal die Aufrufliste, die erscheint wenn es kracht.
    Vielleicht könntest du mir bitte erklären wie ich darazs sehe, wer wen aufgerufen hat.
    ntdll.dll!7c901230()
    ntdll.dll!7c96c943()
    ntdll.dll!7c949eb9()
    > mfc71d.dll!CThreadSlotData::GetThreadValue(int nSlot=14837864) Zeile 269 C++
    mfc71d.dll!CThreadSlotData::GetThreadValue(int nSlot=3) Zeile 269 C++
    mfc71d.dll!CThreadLocalObject::GetData(CNoTrackObject * (void)* pfnCreateObject=0x7c29dc40) Zeile 414 + 0x11 C++
    mfc71d.dll!CThreadLocal<AFX_MODULE_THREAD_STATE>::GetData() Zeile 177 + 0xd C++
    mfc71d.dll!AfxGetModuleThreadState() Zeile 243 C++
    0012e1b8()
    mfc71d.dll!CMapPtrToPtr::GetValueAt(void * key=0x002203fe) Zeile 185 + 0xc C++
    mfc71d.dll!CHandleMap::LookupPermanent(void * h=0x002203fe) Zeile 116 + 0x16 C++
    mfc71d.dll!CWnd::AssertValid() Zeile 888 + 0xf C++
    mfc71d.dll!CView::AssertValid() Zeile 500 C++
    mfc71d.dll!CFormView::AssertValid() Zeile 272 C++
    Par.exe!CParView::AssertValid() Zeile 1978 C++
    0000000a()
    ntdll.dll!7c96d6aa()
    user32.dll!77d4882a()
    user32.dll!77d4c63f()
    ntdll.dll!7c949d18()
    mfc71d.dll!CWnd::DefWindowProcA(unsigned int nMsg=1238036, unsigned int wParam=2082654585, long lParam=32) Zeile 1024 + 0x20 C++
    mfc71d.dll!CThreadLocal<_AFX_THREAD_STATE>::GetData() Zeile 177 + 0xd C++
    00000001()
    user32.dll!77d4d4ee()



  • Hab mein Problem immer noch nicht gelöst.
    Kann mir denn niemand helfen??



  • Wenn innerhalb der Methode "CMainFrame::OnViewDisplay()" ein Fenster erzeugt wird, dann sollte es seine eigene Warteschleife haben :

    // statt :
    
    while (::PeekMessage(&Msg, NULL,0,0,PM_NOREMOVE)) 
    { 
      if (!AfxGetApp()->PumpMessage()) {::PostQuitMessage  (0); break;} 
    } 
    
    // probier mal :
    
    while (::PeekMessage(&Msg, NULL,0,0,PM_REMOVE)) 
    { 
     ::TranslateMessage (&Msg);
     ::DispatchMessage  (&Msg);
    }
    


  • hmm, mal ausprobieren.



  • Nö, das funktioniert auch nicht!!!


Anmelden zum Antworten