Unerlaubter Speicher zugriff *verzweifel* ist CRecordset schuld?



  • Moin Leute,
    ich bin total fertig. Hab schon alles versuch meinen Fehler zu finden aber mit dem debugger tritt der Fehler nicht auf. Und wenn er auftritt ist das auch immer an einer anderen Stelle.

    Ich hab den CRecordset im verdacht. Darf ich da vieleicht nicht so viele instanzen auf eine Datenbank zeigen lassen wie ich will?

    Also ich hab folgenes. Zwei CTreeCtrls. Die werden beide aus meiner Datenbank befüllt. Und das Rekulsive.

    Vieleicht mag sich das mal jemand anschauen, also Funktionieren tuht das alles. Nur ab und zu Stürtzt alles ohne grund ab wenn diese Funktion aufgerufen wird.

    ////////////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    HTREEITEM CVerlaufsBaumDlg::GetTraeger(bool bPreBaum, int nID, HTREEITEM LastItem /*=NULL*/ )
    {
    	////////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    	CTreeCtrl			*pCtrlTree = NULL;					// Welche Liste gemeint ist
    	CRecordset			TempRecordset(&m_mypGAG->m_Database.m_Database);	// eigenen Recordset, da dieser Reculsive benutzt wird
    	CString				csQuery;							// SQL Query
    	CDBVariant			cdbValue;							// SQL Return
    	HTREEITEM			ThisItem = NULL;					// Zeiger auf das Item was jetzt eingefügt wird 
    	sTraeger			Traeger;							// struct sTraeger { int nID; CString csTraegername; };
    	////////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    
    	////////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    	if(bPreBaum)											// richtigen CTreeCtrl aussuchen
    		pCtrlTree = &m_CtrlLinksBaum;
    	else
    		pCtrlTree = &m_CtrlRechtsBaum;
    	////////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    
    	////////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    	if(!m_mypGAG->m_Database.m_Database.IsOpen() || pCtrlTree == NULL )
    		return(NULL);
    	////////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    
    	////////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    	if(bPreBaum)	
    		csQuery = GetPreQuery(nID); // mySQL Query hohlen
    	else
    		csQuery = GetSufixQuery(nID);
    	////////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    
    	////////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    	TempRecordset.Open(CRecordset::forwardOnly, csQuery, CRecordset::readOnly);
    	csQuery.Empty();										// Speicher freigeben
    	////////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    
    	////////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    	while( !TempRecordset.IsEOF() )
    	{
    		////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    		// ID hohlen
    		TempRecordset.GetFieldValue( "ID", cdbValue, SQL_C_SLONG  );
    		if(cdbValue.m_dwType == DBVT_LONG)
    			Traeger.nID = cdbValue.m_lVal;
    		else
    		{													// keine ID keinen eintrag!
    			cdbValue.Clear();
    			TempRecordset.MoveNext();
    			continue;
    		}
    		cdbValue.Clear();
    		////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    
    		////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    		TempRecordset.GetFieldValue( "NAME", cdbValue, SQL_C_CHAR );
    		if(cdbValue.m_dwType == DBVT_ASTRING)
    			Traeger.csTraegername = *cdbValue.m_pstring;
    		else
    		{													// keine ID keinen eintrag!
    			cdbValue.Clear();
    			TempRecordset.MoveNext();
    			continue;
    		}
    		cdbValue.Clear();
    		////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    
    		////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    		ThisItem = pCtrlTree->InsertItem(TVIF_TEXT, Traeger.csTraegername, NULL, NULL, NULL, NULL, Traeger.nID, LastItem, NULL );
    		Traeger.csTraegername.Empty();
    		if(ThisItem != NULL)
    		{
    			pCtrlTree->SetItemData(ThisItem, Traeger.nID);
    			GetTraeger(bPreBaum, Traeger.nID, ThisItem);
    		}
    		////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    
    		////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    		TempRecordset.MoveNext();
    		////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    	}
    	////////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    
    	////////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    	if(TempRecordset.IsOpen()) TempRecordset.Close();
    	////////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    
    	////////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    	return(ThisItem);
    	////////////////////////////////////////////////////////\\///////////////////////////////////////////////////////////////
    


  • Ich glaube mal eher das die Rekursion an Deinem sporadischem Problem schuld ist. Dabei wird sehr viel Speicher verbraucht und irgendwann kann sich ein Stack-Overflow einstellen. Rekusionsfunktionen sollten nie viele lokale Variablen ect. verwenden, da diese zusätzlich den Funktions-Stack belasten.

    Ich vermute mal, dass Du die Funktion rekursiv solange Aufrufst, wie bestimmte Datensätze in der Datenbank gefunden wurden. Also z.B. nach einer Suchanfrage an die DB. Je nach dem, wieviele Datensätze gefunden wurden, läuft die Rekursion. Werden da mal viele Datensätze gefunden kann das sehr Problematisch im Sinne des Speicherbedarfs werden. 😡

    Versuch mal genau nachzuvollziehen wann die Anwendung unter welchen Bedingungen abstürzt. Ist das Problem eventl. reproduzierbar? Wenn ja unter welchen Bedingungen...

    Trotzdem würde ich nicht raten die Listen über Rekursionen aufzubauen, vor allem dann nicht, wenn die Menge der DS unvorhersagbar groß sein kann.

    Gruss René 😉


Anmelden zum Antworten