Wenn CString Memberfunktionen Müll liefern...



  • Hi,

    Getter liefert das gesamte Datenstruct zurück:

    InitFileData A::getInitFileData()
    {
    	return m_strInitFileData;
    }
    

    Im Hauptprogramm:

    m_pDevice_1 = new B;
    InitDevice strDevice1_Init = {0, m_pA->getInitFileData().sSerialNumber1, false};
    
    if (!m_pDevice_1->initDevice(strDevice1_Init))
    {
    ...
    }
    

    Hier die Wandlung anstatt

    strInitDevice.sSerialNumber.IsEmpty()
    

    welches immer 0 liefert obowhl der String richtig drin ist.

    bool B::initDevice(InitDevice strInitDevice)
    {
    	// Explizie Wandlung nach LPCTSTR ist notwendig weil sonst die CString Memberfunktion nur Muell zurueckliefern!
    	CString sSerialNumber = (LPCTSTR) strInitDevice.sSerialNumber;
    
    	if (sSerialNumber.IsEmpty())
    	{
    		return false;
    	}
    
    	if (sSerialNumber.GetLength() != 6)
    	{
    		return false;
    	}
    	m_strInitDevice = strInitDevice;
    	return true;
    };
    

  • Mod

    Das kann nicht sein. Wenn da Müll raus kommt, dann ist Dein Objekt kaputt. Denn bei Zuweisungen von CString an CString wird Referenzzählung verwendet.
    Ist das Quellobjekt Schrott ist auch das Zielobjekt Schrott.



  • Hi,

    wie kann das sein? Im Debugger sehe ich den korrekten Inhalt. Wie kann dann das Objekt im Eimer sein?


  • Mod

    Nein. Du siehst den Zeiger auf den Text-Block. Davor steht aber ein Usage Count und die Länge des Objektes.

    CString verhält sich wie ein Zeiger, aber es ist eben keiner.

    Ein CString ist nichts anderes als ein Zeiger hinter die folgende Struktur, sie wie folgt aussieht:

    struct CStringData
    {
    	IAtlStringMgr* pStringMgr;  // String manager for this CStringData
    	int nDataLength;  // Length of currently used data in XCHARs (not including terminating null)
    	int nAllocLength;  // Length of allocated data in XCHARs (not including terminating null)
    	long nRefs;     // Reference count: negative == locked
    	// XCHAR data[nAllocLength+1]  // A CStringData is always followed in memory by the actual array of character data
    

    Du siehst nur den Zeiger, der hinter diese Struktur zeigt, also auf den XHAR data Teil.

    Wenn Du also Deine Objekte kaputt machst, oder die Referenzzählung zerstört wird, dann kann alles passieren. Oder mit temporären Objekten auf unerlaubte Weise rumspielst kann so was sehr wohl passieren.

    Der CString ist dann defekt. (nicht mehr da), was Du siehst ist nur noch der alte Speicherinhalt.

    Ich bin mir zu 100% sicher:
    Was hier passiert liegt sicherlich nicht an CString, sondern an Deinem Code.

    Nur mal so: Die Länge eines CString wird also ausgelesen aus dem Data Teil. Wenn man also mit GetBuffer den Speicher verändert und die länge nicht korrekt setzt (ReleaseBuffer), dann kommt auch Schrott dabei rum.

    PS: Dein Name impliziert eigentlich, dass Du solche Dinge wissen müsstest SCNT 😉



  • Martin Richter schrieb:

    Was hier passiert liegt sicherlich nicht an CString, sondern an Deinem Code.

    Korrekt deshalb frage ich ja.
    Mittlerweile scheints als ob der getter nix taugt.

    InitFileData A::getInitFileData()
    {
        return m_strInitFileData;
    }
    

    Gibts da nix besseres?

    Martin Richter schrieb:

    PS: Dein Name impliziert eigentlich, dass Du solche Dinge wissen müsstest SCNT 😉

    Eher was ich mache, nicht daß ich alles weiß. 😉


  • Mod

    Hast Du mal ein Mini-Sample, dass ich mir ansehen kann?



  • Martin Richter schrieb:

    Hast Du mal ein Mini-Sample, dass ich mir ansehen kann?

    Hmm..? Ein kleines lauffähiges Projekt zum rausgeben? Geht leider net, da dies zu einem größeren Projekt gehört. Ein Zusammenschrumpfen wäre etwas aufwendig.

    Mittlerweile habe ich weiter nachgeforscht. Ursache ist wohl eine Templatespezifikation für PrivateProfileString.

    template <>bool readParam (CString sParameterName, CString &Value)
    {
    	int nReturn = 0;
    	CString sBuffer = "";
    
    	nReturn = GetPrivateProfileString(m_sParamterGroup, sParameterName, NULL, sBuffer.GetBuffer(m_nBufferLength-1), m_nBufferLength, m_sFilename);
    	if (nReturn == 0)
    	{
    		m_lLastError = ERROR_CANT_READ_PRIVPROFILESTRING;
    		return false;
    	}
    	else
    	{
    		Value = /*(LPCTSTR)*/ sBuffer;
    		return true;
    	}
    }
    

    Wenn der kommentierte Cast aktiv ist klappts.


  • Mod

    Siehst Du: sBuffer.GetBuffer(m_nBufferLength-1)

    Was soll der Mist? Ich schreibe Dir doch noch, dass Du nicht mit GetBuffer rumspielen sollst, sondern bitte dann auch ReleaseBuffer ausführst.

    Was passiert?
    sBuffer ist leer. Die Länge ist 0!!!!
    Du lädst was rein über den Puffer, den Du mit GetBuffer holst, machst aber kein ReleaseBuffer! Die Folge: Die Länge bleibt 0!!!!

    Du hast selbst diesen Scheiß verbrochen. Das steht sogar explizit in der MSDN drin: GetBuffer erzwingt ReleaseBuffer. (Was eigentlich so hart gar nicht stimmt.)

    Verwende CStrBuf und Du hast keine Schmerzen:

    nReturn = GetPrivateProfileString(m_sParamterGroup, sParameterName, NULL, CStrBuf(sBuffer,m_nBufferLength), m_nBufferLength, m_sFilename);
    

    BTW: Warum eigentlich nBufferLength-1?

    Ja ja: Aber "CString liefert Müll..." 😉 Ich sage nur: Shit in, shit out!



  • * Die Templatefunktion ist schon etwas älter und habe mir das noch nicht genau angeschaut.
    * CStrBuf kannte ich bis jetzt noch nicht.
    * Die GetProfile Funktion hab ich, so wie sie dasteht, direkt von einem Beispiel aus dem Internet 1:1 übernommen. Hat damals getan und es gab keinen Grund sie ausführlich zu prüfen. Der Fall jetzt trat eben zum 1.Mal auf.

    Danke für die Hilfe.


  • Mod

    MFC-Coder schrieb:

    * Die GetProfile Funktion hab ich, so wie sie dasteht, direkt von einem Beispiel aus dem Internet 1:1 übernommen. Hat damals getan und es gab keinen Grund sie ausführlich zu prüfen. Der Fall jetzt trat eben zum 1.Mal auf.

    Nein! Der Fehler war schon immer da. Das CString Objekt war niemals korrekt.

    Tolle Quelle. Aber so ist das: Schrott verbreitet sich durch CPP (Copy Paste Programming) schneller als jeder gescheite Code. 😉


Anmelden zum Antworten