Filou Geschrieben 28. Juli 2006 Geschrieben 28. Juli 2006 Hi! Ich habe das Problem, das mein Programm im Debug-Modus ohne Fehler läuft aber wenn ich es als Release erstelle stüzt es ab. Es kommt der Fehler: Die Anweisung in "0x73d311x7" verweiß auf den Speicher in "0x00000139". Der Vorgang "read" konnte auf dem Speicher nicht ausgeführt werden. Wie kann ich denn rausfinden wo der Fehler liegt wenn es im Debug-Modus ganz normal läuft? Hab schon bereinigt und neu erstellt... Woran kann das liegen? Gruß Filou Zitieren
Filou Geschrieben 28. Juli 2006 Autor Geschrieben 28. Juli 2006 Habe jetzt rausgefunden dass es wohl an pWnd->PostMessage(WM_CHECKTERMINE, 0, 0); liegt. Das wird in einem Thread gemacht. Wenn ich es auskommentiere gehts auch als Release Aber wieso läuft es unter Debug? Und was kann daran falsch sein? Zitieren
Klotzkopp Geschrieben 28. Juli 2006 Geschrieben 28. Juli 2006 Probleme im Release, die im Debug nicht auftreten, haben meist eine der folgenden Ursachen: - uninitialisierte Variablen - Arraybereichsüberschreitungen - mangelnde Synchronisation In der Debugversion werden Variablen automatisch mit bestimmten Werten initialisiert. Außerdem wird rund um dynamisch angelegten Speicher ein Pufferbereich angelegt, so dass Bereichsüberschreitungen nicht gleich andere Variablen überschreiten. Und natürlich ist bei Release durch die Optimierung das Zeitverhalten, gerade bei mehreren Threads anders. Wenn man da nicht ordentlich synchronisiert hat, knallt's eben. Zitieren
Guybrush Threepwood Geschrieben 28. Juli 2006 Geschrieben 28. Juli 2006 Das Problem wird nicht das Posten von WM_CHECKTERMINE sein, sondern die Reaktion auf diese Nachricht Zitieren
Filou Geschrieben 28. Juli 2006 Autor Geschrieben 28. Juli 2006 Ich habe nen Haltepunkt in die Funktion gemacht die durch WM_CHECKTERMINE aufgerufen wird. Ganz oben. Aber das programm sürtzt vorher ab. Also kanns doch nicht an einer Variable liegen, die ich angelegt habe, oder?? :confused: PS: Der fehler passiert in der MFC42.DLL Aufrufliste: MFC42! 73d311c7() Register: EAX = 00000111 EBX = 77D1D7F9 ECX = 00000135 EDX = 0033E7C8 ESI = 0012F35C EDI = 0012F35C EIP = 73D311C7 ESP = 0012C67C EBP = 0044AEA4 EFL = 00000206 Zitieren
Klotzkopp Geschrieben 29. Juli 2006 Geschrieben 29. Juli 2006 Also kanns doch nicht an einer Variable liegen, die ich angelegt habe, oder?? :confused:Welchen Wert hat pWnd denn an dieser Stelle? Die Fehlermeldung könnte auf einen Nullzeiger hinweisen. Aufrufliste: MFC42! 73d311c7()Ist das wirklich die ganze Aufrufliste? Zitieren
Schnitzelfritz Geschrieben 3. August 2006 Geschrieben 3. August 2006 Wenn ich das Problem richtig verstanden habe dann versuchst du aus einem Thread über eine Zeigervariable eines Fenster eine Nachricht an einen anderen Thread zu schicken. Hat der Thread der die Nachricht abschickt das Fenster erstellt? Du kannst keine MFC Objekte über Threadgrenzen hinweg durchreichen. Was du machen kannst ist den Window Handle übergeben und die normale API Funktion ::SendMessage(HWND,UINT,WPARAM,LPARAM) verwenden. Zitieren
Filou Geschrieben 3. August 2006 Autor Geschrieben 3. August 2006 Wenn ich das Problem richtig verstanden habe dann versuchst du aus einem Thread über eine Zeigervariable eines Fenster eine Nachricht an einen anderen Thread zu schicken. Hat der Thread der die Nachricht abschickt das Fenster erstellt? Du kannst keine MFC Objekte über Threadgrenzen hinweg durchreichen. Was du machen kannst ist den Window Handle übergeben und die normale API Funktion ::SendMessage(HWND,UINT,WPARAM,LPARAM) verwenden. Danke für den Tip. Ich bin nicht sicher ob ichs richtig gemacht habe. Also ursprünglich hatte ich es so: pWnd->PostMessage(WM_CHECKTERMINE, 0, 0); Da ging der Dialog auf und das Programm ist beim schließen des Dialogs abgesürzt. (Die Nachricht soll eine Funktion starten die einen Dilaog modal öffnet) Jetzt habe ichs so versucht: pWnd->SendMessage(WM_CHECKTERMINE,0,0); Da stützt das Programm gleich ab. Und so habe ichs auch versucht: SendMessage(HWND_BROADCAST,WM_CHECKTERMINE,0,0); Da passiert aber garnix. Das alles hier steht in dem Thread. Zitieren
Filou Geschrieben 3. August 2006 Autor Geschrieben 3. August 2006 Welchen Wert hat pWnd denn an dieser Stelle? Die Fehlermeldung könnte auf einen Nullzeiger hinweisen. Ist das wirklich die ganze Aufrufliste? Ja das war die ganze Aufrufliste. pWnd kann ich an der Stelle wos knallt nicht mehr sehen. Zitieren
Schnitzelfritz Geschrieben 3. August 2006 Geschrieben 3. August 2006 Probier mal PostThreadMessage(DWORD idThread,UINT Msg,WPARAM wParam,LPARAM lParam); Die Frage ist jetzt nur noch, ob du deinen pWnd Zeiger auch in dem Thread erzeugst oder im Hauptapplikationsthread. Wie sieht deine Threadfunktion aus? Was übergibst du ihr als Parameter? Zitieren
Filou Geschrieben 3. August 2006 Autor Geschrieben 3. August 2006 Das geht auch nicht (es passiert garnix): PostThreadMessage(0,WM_CHECKTERMINE,0,0); Wobei ich nicht weiß ob das richtig ist wenn ich immer nur 0 angebe. Ich habe ja keine Zielthread für die Nachricht. Das Ziel ist eine Memberfunktion in der Klasse meines Dialogs bzw die Message Map die dann die Memberfunktion starten soll. Es lässt sich kompilieren, stürtzt dann aber auch ab. Vielleicht liegt es an etwas ganz anderem?? Ich will einfach nur diese Funktion starten die einen Dialog öffnet Das einzige was bis jetzt die Funktion gestartet hatte war PostMessage. Es ist halt nur nach dem schließen des Dialogs, der durch die Funktion geöffnet wurde, abgestürzt. Zitieren
Schnitzelfritz Geschrieben 3. August 2006 Geschrieben 3. August 2006 Hm, ich glaub so wird das nichts. Kannst du vielleicht den Quellcode zur Verfügugn stellen, so dass man sich das mal anschauen kann? Zitieren
Filou Geschrieben 7. August 2006 Autor Geschrieben 7. August 2006 Danke, dass Du mir hilfst!! Also hier ist mal ein bissel Code. BEGIN_MESSAGE_MAP(CPatient, CDialog) //{{AFX_MSG_MAP(CPatient) ON_MESSAGE(WM_CHECKTERMINE, OnCheckTermine) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // Therad definieren //BOOL m_bThreadEnd; UINT DBUeberwachung(void* pParam) { CPatient *pWnd; pWnd=(CPatient*)pParam; int iCounter = 0; //Dieser Thread überprüft alle 30 Sekunden die Verbindung zur Datenbank //und aktuallisiert die die Anzeige. while (g_iDBUeberwachung != 5555) //ENDLOS { //DATENBANKÜBERWACHUNG AKTIV if(g_iDBUeberwachung == SERVICE_START) { pWnd->PostMessage(WM_KEYDOWN,VK_F5,0); // Simulieren, dass die F5-Taste gedrückt wurde // Zur Aktuallisierung der Dokumentenliste // Und zur Prüfung des Status der Datenbank if(iCounter == 5) // Nur jede 10 Datenbankprüfung auch Termine Prüfen { // pWnd->PostMessage(WM_CHECKTERMINE, 0, 0); //Prüfen ob neue Termine vorliegen pWnd->SendMessage(WM_CHECKTERMINE,0,0); iCounter = 0; } iCounter++; Sleep(10000); } //DATENBANKÜBERWACHUNG BEENDEN if(g_iDBUeberwachung == SERVICE_STOP) { return (1); } } // return (0); } ///////////////////////////////////////////////////////////////////////////// // Diaologinitialisierung BOOL CPatient::OnInitDialog() { //Thread zur Datenbanküberwachung starten g_iDBUeberwachung = SERVICE_START; CWinThread *pThread = AfxBeginThread(DBUeberwachung, this, THREAD_PRIORITY_NORMAL); } void CPatient::OnCheckTermine() { //Hier kommt das Programm nie an, stürtzt vorher ab. } Wenn Du nochwas sehen willst, sag bescheid!! Zitieren
Schnitzelfritz Geschrieben 7. August 2006 Geschrieben 7. August 2006 Probier mal folgendes: (notfalls den Adressoperator und die Derefernzierung weglassen. Mein C++ ist etwas eingerostet ) BEGIN_MESSAGE_MAP(CPatient, CDialog) //{{AFX_MSG_MAP(CPatient) ON_MESSAGE(WM_CHECKTERMINE, OnCheckTermine) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // Therad definieren //BOOL m_bThreadEnd; UINT DBUeberwachung(void* pParam) { CPatient *pWnd; pWnd=(CPatient*)[B]CWnd::FromHandle ( (HWND)*pParam )[/B]; int iCounter = 0; //Dieser Thread überprüft alle 30 Sekunden die Verbindung zur Datenbank //und aktuallisiert die die Anzeige. while (g_iDBUeberwachung != 5555) //ENDLOS { //DATENBANKÜBERWACHUNG AKTIV if(g_iDBUeberwachung == SERVICE_START) { pWnd->PostMessage(WM_KEYDOWN,VK_F5,0); // Simulieren, dass die F5-Taste gedrückt wurde // Zur Aktuallisierung der Dokumentenliste // Und zur Prüfung des Status der Datenbank if(iCounter == 5) // Nur jede 10 Datenbankprüfung auch Termine Prüfen { // pWnd->PostMessage(WM_CHECKTERMINE, 0, 0); //Prüfen ob neue Termine vorliegen pWnd->SendMessage(WM_CHECKTERMINE,0,0); iCounter = 0; } iCounter++; Sleep(10000); } //DATENBANKÜBERWACHUNG BEENDEN if(g_iDBUeberwachung == SERVICE_STOP) { return (1); } } // return (0); } ///////////////////////////////////////////////////////////////////////////// // Diaologinitialisierung BOOL CPatient::OnInitDialog() { //Thread zur Datenbanküberwachung starten g_iDBUeberwachung = SERVICE_START; CWinThread *pThread = AfxBeginThread(DBUeberwachung, [B]&this -> GetSafeHwnd()[/B], THREAD_PRIORITY_NORMAL); } void CPatient::OnCheckTermine() { //Hier kommt das Programm nie an, stürtzt vorher ab. } Zitieren
Filou Geschrieben 8. August 2006 Autor Geschrieben 8. August 2006 Hey, danke für die Antwort! Hier: pWnd=(CPatient*)CWnd::FromHandle ( (HWND)*pParam ); bekomme ich aber gesagt: Zeigeroperation ungueltig Zitieren
Filou Geschrieben 8. August 2006 Autor Geschrieben 8. August 2006 PS: OHNE den * bei pWnd=(CPatient*)CWnd::FromHandle ( (HWND)[COLOR="Red"][B]*[/B][/COLOR]pParam ); lässt es sich kompilieren und stürst auch nicht ab, jedoch wird bei pWnd->PostMessage(WM_CHECKTERMINE,0, 0); //Prüfen ob neue Termine vorliegen //ODER pWnd->SendMessage(WM_CHECKTERMINE,0,0); die entsprechende Funktion nicht aufgerufen. Zitieren
Schnitzelfritz Geschrieben 8. August 2006 Geschrieben 8. August 2006 Dann probiers mal ohne Adressoperator: CPatient *pWnd; pWnd=(CPatient*)CWnd::FromHandle ( (HWND)[B]pParam[/B] ); ... CWinThread *pThread = AfxBeginThread(DBUeberwachung, [B]this -> GetSafeHwnd()[/B], THREAD_PRIORITY_NORMAL); Zitieren
Filou Geschrieben 8. August 2006 Autor Geschrieben 8. August 2006 Das macht leider keinen Unterschied. Die Nachricht ruft die Funktion nicht auf Zitieren
Schnitzelfritz Geschrieben 9. August 2006 Geschrieben 9. August 2006 Hi Filou, dein Problem hat mich nicht mehr losgelassen, daher hab ich mir mal schnell ein Test Projekt nachgebaut. (Code ist mit VS .Net 2003 erstellt). Bei mir wurde der Nachrichtenhandler ohne Probleme geöffnet als ich in der Threadfunktion PostMessage verwendet habe. Benutzt du VS 6.0? Da ist der Compiler etwas fehlertoleranter, wenn dein Nachrichtenhandler nicht die richtige Signatur für User defined messages (WM_USER) hat. Vielleicht ist das mit ein Grund warum deine Release Build einen Fehler hat. Hier siehst du mein Testprojekt, vielleicht hilfts dir weiter: (Die Implementierung der Threadfunktion habe ich aus deinem Post übernommen. Wichtig ist die Signatur von OnCheckTermine) // CThreadTestDlg Dialogfeld class CThreadTestDlg : public CDialog { // Konstruktion public: CThreadTestDlg(CWnd* pParent = NULL); // Standardkonstruktor ... // Generierte Funktionen für die Meldungstabellen virtual BOOL OnInitDialog(); [B]afx_msg LRESULT OnCheckTermine(WPARAM wParam, LPARAM lParam);[/B] DECLARE_MESSAGE_MAP() }; #define WM_CHECKTERMINE (WM_USER+0x100) BEGIN_MESSAGE_MAP(CThreadTestDlg, CDialog) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_MESSAGE(WM_CHECKTERMINE,OnCheckTermine) //}}AFX_MSG_MAP END_MESSAGE_MAP() UINT DBUeberwachung(LPVOID pParam) { CThreadTestDlg *pWnd; pWnd=(CThreadTestDlg*)pParam; int iCounter = 0; //Dieser Thread überprüft alle 30 Sekunden die Verbindung zur Datenbank //und aktuallisiert die die Anzeige. while (g_iDBUeberwachung != 5555) //ENDLOS { //DATENBANKÜBERWACHUNG AKTIV if(g_iDBUeberwachung == SERVICE_START) { pWnd->PostMessage(WM_KEYDOWN,VK_F5,0); // Simulieren, dass die F5-Taste gedrückt wurde // Zur Aktuallisierung der Dokumentenliste // Und zur Prüfung des Status der Datenbank if(iCounter == 5) // Nur jede 10 Datenbankprüfung auch Termine Prüfen { pWnd->PostMessage(WM_CHECKTERMINE, 0, 0); iCounter = 0; } iCounter++; Sleep(1000); } //DATENBANKÜBERWACHUNG BEENDEN if(g_iDBUeberwachung == SERVICE_STOP) { return (1); } } return (0); } BOOL CThreadTestDlg::OnInitDialog() { CDialog::OnInitDialog(); // Symbol für dieses Dialogfeld festlegen. Wird automatisch erledigt // wenn das Hauptfenster der Anwendung kein Dialogfeld ist SetIcon(m_hIcon, TRUE); // Großes Symbol verwenden SetIcon(m_hIcon, FALSE); // Kleines Symbol verwenden g_iDBUeberwachung = SERVICE_START; CWinThread *pThread = AfxBeginThread ( DBUeberwachung, this, THREAD_PRIORITY_NORMAL ); return TRUE; } [B]LRESULT CThreadTestDlg::OnCheckTermine(WPARAM wParam, LPARAM lParam)[/B] { CAboutDlg dlg; dlg.DoModal(); return 0; } Zitieren
Filou Geschrieben 10. August 2006 Autor Geschrieben 10. August 2006 Hey erstmal vielen Dank, dass Du Dir soviel Mühe gemacht hast! Das ist wirklich super!! Ich hatte gestern Urlaub und konnte es nicht testen. Heute Morgen habe ich aber alles aus Deinem Beispiel übernommen und es klappt jetzt ohne Probleme!! :uli :uli :uli :uli Tausenmal DANKE!! Das ist echt geil!! Wüsster jetzt gern worans gelegen hat?! Vielleicht lags an meiner Funktionsdefinition: void CPatient::OnCheckTermine() Wieso hast Du es so gemacht: LRESULT CPatient::OnCheckTermine(WPARAM wParam, LPARAM lParam) Zitieren
Schnitzelfritz Geschrieben 10. August 2006 Geschrieben 10. August 2006 Toll, dass es jetzt klappt. Ich habe die Funktionssignatur genommen, weil es die standardsignatur für user defined messages der MFC ist. Wenn du Visual Studio 6.0 verwendest dann compiliert alles ohne Probleme. Compilierst du den selben Code z.B. mit Visual Studio .Net 2003 meckert der Compiler sofort wenn deine Funktion nicht dieser Signatur entspricht. Ob das jetzt wirklich genau der Grund war kann ich nicht 100% beantworten aber es ist durchaus möglich da der Absturz nur im Release Build aufgetreten ist. Freut mich auf jeden Fall wenn ich helfen konnte. Zitieren
Filou Geschrieben 10. August 2006 Autor Geschrieben 10. August 2006 Ja ich verwende VC6. Und Du hast mir wirklich sehr geholfen. Ohne Dich wäre ich da nie draufgekommen. Danke nochmal! Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.