Access Violation - auf einmal!?
-
Hi,
ich habe seit Ewigkeiten eine Dialogfeldklasse (ein Einstellungsmenü) die ich in allen Programmen benutze wo ich sie brauche. Ich habe auch seit langem nichts daran verändert.
Jetzt habe ich eben in meinem Programm die Einstellungen aufrufen wollen und ex tritt eine Access violation auf!?
Mir fällt jetzt nichts mehr nach stundenlangem testen
Die gleiche Klasse kann ich in anderen Projekten ERFOLGREICH (!) ausführen.
Symptome:
In der Dialogfeldklasse wird GetParent() aufgerufen was 'NULL' zurück gibt (im Normalfall passiert das nicht).Es hat auch immer in diesem Projekt funktioniert, nur jetzt auf einmal nicht mehr...
Gruß,
Marco
-
Normalerweise übergibst du beim Starten des Dialogs das Elternfenster - vermutlich hast du dort etwas anders gemacht als bisher.
-
Wo wird GetParent aufgerufen. In Deinem Code?
Wie sieht der Callstack aus? Wo kracht es?
-
Mache alles genauso wie bisher - hat ja auch schon alles geklappt. Der Fehler kommt auf einmal...
GetParent() unter Anderem wird in OnInitDialog() aufgerufen.
Ich rufe das Dialogfeld mit DoModal() auf. Wenn ich vorher SetOwner() aufrufe und die Elternklasse übergebe dann klappt es (verwendet in der Dialogfeldklasse dann natürlich immer GetOwner() anstatt GetParent()). Sobald ich das Fenster schließe kommt der selbe Fehler:
"Access violation reading location 0x00000020."
Also eine ungültige Adresse, die Gibt er mir aus wenn ich GetParent() in der Dialogfeldklasse ausführe:
CMyConfigDlg *mConfigDlg; void CMeinProgramm::Funktion() { mConfigDlg = new CMyConfigDlg(this); mConfigDlg->DoModal(); delete mConfigDlg; mConfigDlg = NULL; }
BOOL CMyConfigDlg::OnInitDialog() { //... GetParent()->SendMessage(...) }
-
Was ist this? Ein Fenster? Ist es erzeugt, oder ist m_hWnd NULL?
Debugge mal einfach in DoModal rein. Dann wirst Du sehen, dass irgendwann das Parent bestimmt wird, bevor der Dialog erzeugt wird.
Wird dort auch wirklich dieses this genommen?Nur am Rande:
Warum machst Du ein new und lässt den Dialog nicht einfach auf dem Stack liegen?Das genügt völlig:
void CMeinProgramm::Funktion() { CMyConfigDlg dlg(this); dlg.DoModal(); }
-
This ist das Fenster meine Anwendung.
'm_hWnd' ist "0x00090f98 {unused=0}"...
wenn ich 'm_pParentWnd' anstatt 'GetParent()' in der Dialogfeldklasse benutze dann klappt es vorerst. Sobald ich das Fenster schließe kommt der Fehler dann wie gehabt.
Ich erbe von einer Klasse, welche dann über eine Weitere Klasse von CDialog erbt. Die Klasse überschreibt 'DoModal()':
int CDynModalDlg::DoModal(InitDynDlg iInitInfo) { LOGFONT lLogFont; WCHAR *wFontName, *wBoxCaption; HLOCAL hLocal; int iWndCaption, iFontNameLen, iBoxLen, iBufSize; if (iInitInfo.rDlgPos.Width() < DMDM_MIN_WIDTH) // Breite korregieren: iInitInfo.rDlgPos.right = iInitInfo.rDlgPos.left + DMDM_MIN_WIDTH; if (iInitInfo.rDlgPos.Height() < DMDM_MIN_HEIGHT) // Breite korregieren: iInitInfo.rDlgPos.bottom = iInitInfo.rDlgPos.top + DMDM_MIN_HEIGHT; // Template einrichten: dDlgTmpl.style = iInitInfo.dStyle; dDlgTmpl.dwExtendedStyle = iInitInfo.dStyleEx; dDlgTmpl.cdit = 0; dDlgTmpl.x = iInitInfo.rDlgPos.left; dDlgTmpl.y = iInitInfo.rDlgPos.top; dDlgTmpl.cx = iInitInfo.rDlgPos.Width(); dDlgTmpl.cy = iInitInfo.rDlgPos.Height(); // Fint-Informationen ermitteln: if ((iInitInfo.fFont == NULL) && (m_pParentWnd != NULL)) // Font von Parent ermitteln: iInitInfo.fFont = m_pParentWnd->GetFont(); if ((iInitInfo.fFont == NULL) && (AfxGetApp()->m_pActiveWnd != NULL)) // Font von Applikation ermitteln: iInitInfo.fFont = AfxGetApp()->m_pActiveWnd->GetFont(); // LOGFONT einrichten: memset(&lLogFont, 0x00, sizeof(lLogFont)); if (iInitInfo.fFont != NULL) iInitInfo.fFont->GetLogFont(&lLogFont); else { strcpy(lLogFont.lfFaceName, _T("MS Sans Serif")); lLogFont.lfHeight = 8; } // Font einrichten: iWndCaption = MultiByteToWideChar(CP_ACP, 0, lLogFont.lfFaceName, -1, NULL, 0); iFontNameLen = iWndCaption + 1; wFontName = new WCHAR[iFontNameLen]; // Fontnamen kopieren: MultiByteToWideChar(CP_ACP, 0, lLogFont.lfFaceName, -1, (LPWSTR) wFontName, iWndCaption); iFontNameLen = (iWndCaption) * sizeof(WCHAR); wFontName[iWndCaption] = 0; // Fenstertitel einrichten: iWndCaption = MultiByteToWideChar(CP_ACP, 0, iInitInfo.cDlgTitle, -1, NULL, 0); iBoxLen = iWndCaption + 1; wBoxCaption = new WCHAR[iBoxLen]; // Fenstertitel kopieren: MultiByteToWideChar(CP_ACP, 0, iInitInfo.cDlgTitle, -1, (LPWSTR) wBoxCaption, iWndCaption); iBoxLen = (iWndCaption) * sizeof(WCHAR); wBoxCaption[iWndCaption] = 0; // Puffergröße bestimmen: // - DLGTEMPLATE // - Menü / Klasse // - Captiongröße // - Fontgröße // - Größe Fontname iBufSize = sizeof(DLGTEMPLATE) + (2 * sizeof(WORD)) + iBoxLen + sizeof(WORD) + iFontNameLen; // Speicher zuweisen: hLocal = LocalAlloc(LHND, iBufSize); if (hLocal != NULL) { BYTE *pdest, *pBuffer; // Speicher sperren: pBuffer = (BYTE*) LocalLock(hLocal); if (pBuffer != NULL) { INT_PTR iReturnVal = -1; pdest = pBuffer; // Daten in Puffer kopieren: memcpy(pdest, &dDlgTmpl, sizeof(DLGTEMPLATE)); // 'DLGTEMPLATE' Struktur kopieren pdest += sizeof(DLGTEMPLATE); *(WORD*) pdest = 0; // KEIN Menü einrichten ( >> 0 Bytes) pdest += sizeof(WORD); *(WORD*) (pdest + 1) = 0; // Standard Window-Klasse benutzen ( >> 0 Bytes) pdest += sizeof(WORD); memcpy(pdest, wBoxCaption, iBoxLen); // Caption pdest += iBoxLen; *(WORD*)pdest = (int) lLogFont.lfHeight; // Fontgröße pdest += sizeof(WORD); memcpy(pdest, wFontName, iFontNameLen); // Fontname pdest += iFontNameLen; // Sicherstellen, dass Heap nicht überlaufen wird: ASSERT((pdest - pBuffer) == iBufSize); if (m_lpDialogTemplate != NULL) // Sicherstellen, dass keine Assertion beim drücken von 'Previous' / 'Next' auftritt: m_lpDialogTemplate = NULL; if (InitModalIndirect((LPDLGTEMPLATE)pBuffer, m_pParentWnd)) { // Initialisierungsinformationen übernehmen: this->iInitInfo = iInitInfo; // Dialogfeld modal anzeigen: iReturnVal = CSizeDialog::DoModal(); } // Restarbeiten: LocalUnlock(hLocal); LocalFree(hLocal); delete [] wBoxCaption; delete [] wFontName; return (iReturnVal); } } return (-1); }
Es wird ein Template erstellt und 'InitModalIndirect()' aufgerufen. CSizeDialog hängt da zwar auch noch drin aber damit hab ich nie Probleme gehabt. Ich behaupt das liegt nicht daran.......
Ich erzeuge das Dialogfeld mit 'new' weil ich vorher auf die Adresse gucke ob das Fenster schon erzeugt ist (wenn ja: dann 'SetForegroundWindow()').
-
...es kann doch nur irgendetwas allgemeines sein!?
Bin seit Monaten an dem Programm und das Dialogfeld funktioniert immer, und jetzt auf einmal klappt es nicht mehr!?
EDIT:
Es läuft...vor DoModal lege ich eine lokale Variable an 'ConfigValues cConfigTmp' (ConfigValues ist eine Struktur mit BOOL, CSize, CString -Werten). Wenn ich die Variable als Membervariable in meiner Hauptdialogfeldklasse anlege funktioniert es!?