new char auch wieder mit delete löschen?



  • Hallo,

    Pointer und sowas wie char* versuche ich so weit wie möglich zu vermeiden. Daher kenne ich mich damit auch eher weniger aus.
    Ich meine aber mich daran zu erinnern, dass alles, was mit new erzeugt wird, auch wieder mit delete gelöscht werden muss.
    Jetzt habe ich das hier gefunden, was mir weiter hilft und auf den ersten Blick (bei ersten Tests) auch funktioniert.

    Aber:
    erzeugt das Speicherlecks? Ist das eine Zeitbombe? Muss pszBuffer nicht auch wieder mit delete gelöscht werden?

    char* CStringToChar(CString strIn)
    {
      char* pszBuffer = new char[strIn.GetLength()+1];
      strcpy(pszBuffer, strIn);
      return pszBuffer;
    }
    

    Wäre prima, wenn mir jemand dazu etwas erklären könnte.
    Vielen Dank dafür schon mal im Voraus.



  • mit Sicherheit mußt du den reservierten Speicher wieder frei geben. Wobei deine Funktion etwas Sinnfrei ist, da du einen Zeiger auf den Buffer auch mit GetBuffer() erhälst und den nicht wieder frei geben mußt. Des weiteren ist es Sinnvoll Referenzen auf ein Objekt zu übergeben, außer die Funktion Benutzt die übergabe und verändert sie während der Verarbeitung

    char* CStringToChar(CString &strIn)
    {
      char* pszBuffer = new char[strIn.GetLength()+1];
      strcpy(pszBuffer, strIn);
      return pszBuffer;
    }
    


  • CTecS schrieb:

    Des weiteren ist es Sinnvoll Referenzen auf ein Objekt zu übergeben, außer die Funktion Benutzt die übergabe und verändert sie während der Verarbeitung

    Und um die Gefahr der Veränderung zu reduzieren, sollte man dann auch eine konstante Referenz übergeben.

    char* CStringToChar(CString const & strIn)
    

    @isabeau: Ganz davon abgesehen das man zu jedem new ein delete, zu jedem new[] ein delete[] benötigt, sollte man diese Aufrufe möglichst auch nicht trennen. Wenn man mal die eingebauten Möglichkeiten der Klasse ignoriert, wäre hier der mögliche ansatz, den Buffer auch als Parameter zu übergeben (Damit der Aufrufer in dem Fall beides in der Hand hat).



  • Eigentlich habe ich in meiner Header-Datei den hier (komme ich nicht drumrum, ist so vorgegeben):

    char * m_Files[100];
    

    In einer Methode fülle ich den mit Namen:

    void CKlasse::Fuelle()
    {
    	m_Files[0] = "eins.txt";
    	m_Files[1] = "zwei.txt";
    	m_Files[2] = "drei.txt";
    }
    

    In einer weiteren Methode muss ich diese Einträge verarbeiten.
    Das obere funktioniert, ist aber fest verdrahtet ungeeignet. Daher möchte ich der Methode den Namen als Parameter (CString) mitgeben:

    void CKlasse::Fuelle(int i, CString Name)
    {
    	char* pszBuffer= new char[Name.GetLength()+1];
    	strcpy(pszBuffer, Name);
    	m_Files[i] = pszBuffer;
    }
    

    Geht, kommt mir aber, wie bereits erwähnt, unsauber vor. Wurde hier ja auch schon bemängelt.
    Bei allen anderen Versuchen, m_Files zu füllen, waren die Inhalte in der folgenden Methode verschwunden. Ich nehme an, das liegt daran, dass die lokalen Variablen dann aus dem Sichtbereich verschwunden sind...

    Einige fehlgeschlagene Versuche, m_Files zu füllen:

    m_Files[0] = strName.GetBuffer(255);
    	m_Files[0] = (LPCTSTR)strName;
    	strcpy((char*)m_Files[0], (const char*)Name);
    	m_Files[0] = (char*)(LPCSTR)Name;
    

    Bei diesen Versuchen stand in der folgenden Methode, die m_Files ausliesst, nur noch Speicherschrott drin:

    void CKlasse::Lese()
    {
    	// m_Files[0] == "cccccccccccccccccccccccc..."; // oder ähnliches
    
    	// Wurde m_Files so gefüllt:
    	// m_Files[0] = "eins.txt"; // dann steht hier auch eins.txt drin
    	// ebenso bei der Lösung mit new char, was aber wohl auch nicht ordentlich ist...
    }
    


  • isabeau schrieb:

    Eigentlich habe ich in meiner Header-Datei den hier (komme ich nicht drumrum, ist so vorgegeben):

    C-Strings (char 😉 lassen sich nicht durch Zuweisung verändern, dazu musst du schon auf die entsprechenden C-Funktionen zugreifen.



  • Aha, danke.
    Daher dachte ich ja, der Weg mit strcpy (erstes Posting) wäre so eine entsprechende C-Funktion...



  • du kannst einen char* füllen aber nicht wenn du den wie du zugewiesen hast, sondern du mußt schon speicher dafür reservieren, also mit:

    file[0] = new[sizeof(char)*100]
    //oder
    file[0] = new char[100];
    

    auf dem Heap reservieren. Dann kannst du auch mit deinem strcpy drauf los gehen. Wobei ich solche sachen für sinnlos und Veraltet Betrachte, da es gerade für Zeichenketten und Arrays schon fertige Klassen gibt dei sicher fehlerfreier sind als das zusammengefrickel. Dazu auch mein erster Post.

    siehe auch:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-39486.html

    @asc:
    mir leuchtet zwar net wirklich ein warum der CString bei der übergabe unbedingt ein const objekt sein sollte, aber vielleicht kann ich da auch noch was lernen



  • Danke, werde ich mir morgen mal genauer ansehen.



  • CTecS schrieb:

    mir leuchtet zwar net wirklich ein warum der CString bei der übergabe unbedingt ein const objekt sein sollte, aber vielleicht kann ich da auch noch was lernen

    Muss nicht, aber es schützt vor versehentlicher Veränderung des Strings.


  • Mod

    CString hat die Funktion GetBuffer um auf den Speicher direkt zugreifen zu können!

    CString muss einen const Zeiger zurückliefern, denn es werden ja bei Kopien eines Strings Referenzzählung durchgeführt. Wird ein nicht const CString erwartet muss erst evtl. eine schreibbare Kopie des CString Objektes angefertigt werden.
    Das hat nicht nur was mit Sicherheit zu tun, sondern eben auch mit der Implementierung.



  • CTecS schrieb:

    @asc:
    mir leuchtet zwar net wirklich ein warum der CString bei der übergabe unbedingt ein const objekt sein sollte, aber vielleicht kann ich da auch noch was lernen

    Grundsätzlich reduzierst du potentielle Fehlerquellen, wenn du bei Daten die nicht geändert werden sollen, ein const verwendest. Ganz davon abgesehen hat eine const-Referenz noch einen Vorteil, du kannst auch mit Temporären Übergaben arbeiten (das schließt Defaultwerte mit ein):

    void foo1(std::string & a);
    void foo2(std::string const & a);
    
    //...
    int main()
    {
        std::string a;
        foo1(a);      // klappt
        foo1("Test"); // klappt nicht
        foo2(a);      // klappt
        foo2("Test"); // klappt
    }
    //...
    

    Zudem sieht man der Funktions-/Methodendeklaration direkt an, ob eine Änderung voraussichtlich vorgesehen ist, oder nicht.

    cu André


Anmelden zum Antworten