malloc verursacht Programmabbruch

mueslirocker

Mitglied
Hallo,

vorweg - ich benutze cygwin und damit den GNU Compiler gcc.

Also, ich hantiere momentan mit sehr großen Strings.
Hab mir eine Klasse dafür geschrieben, die einen Pointer auf einen Char (anfangs NULL) und ein Integer, der die Füllhöhe des Strings speichert, als Member hat. Da ist noch mehr in der Klasse (wie z.B. ein kleiner String statischer Größe, der den Namen des Strings beinhaltet und sowas), aber ich denke mal, das ist hier nicht wichtig.
Im Konstruktor kann man angeben, wie groß der String sein soll.
Mittels malloc suche ich mir dann einen entsprechenden Speicherbereich und lass den Pointer drauf zeigen.

Diese Buffer-Klasse brauche ich öfters.
Ich speichere in dessen Instanzen einen sehr langen String (bis zu 3 MB).
Nebenher lege ich noch 3 Buffer an, die genauso groß sind (einer soll den veränderten String beinhalten und zwei brauche ich als Zwischenspeicher, um Berechnungen an Teilen des Strings durchzuführen).
Mir fällt grad noch ein vierter ein, der einen Verbose-String beinhalten soll.

Und von diesen langen Strings werden werden mehrere pro Programmdurchlauf (wenn auch nacheinander) manipuliert.
Am Ende eines "String-Handlings" wende ich free() auf den char Pointer (nicht auf das Objekt selbst) an.
Also in etwa "free(BufferInstanz->charbuffer);"

Okay, mein Problem ist, dass nach dem dritten oder vierten String-Handling das Programm beim Instanzieren mit Fehlermeldung "xy.exe hat einen Fehler verursacht und wird geschlossen. Starten sie das Programm neu. Ein Fehlerprotokoll wird erstellt" abbricht (btw, ich hatte einen Stackdump oder sowas erwartet, aber ich finde keinerlei Fehlerprotokoll).
Durch Testausgaben habe ich festgestellt, dass genau der malloc Befehl im Konstruktor die Absprungstelle ist.

Wenn ich das Programm geringfügig ändere (die Strings in anderer Reihenfolge behandle oder einen weglasse o.ä.), tritt der Fehler manchmal einen Durchlauf früher oder später auf.. manchmal sogar gar nicht.

Für mich klingt das so, als würde irgendwo ein Speicher überlaufen.
Meine Fragen:

Hat jemand Erfahrungen mit malloc diesbezüglich?

Darf ich malloc überhaupt im Konstruktor der Klasse benutzen?

Muss ich Speicher noch irgendwie anders reservieren oder ander wieder freigeben?

Kann es sein, dass ich einfach zu viel Speicher insgesamt reservieren will? Falls ja, warum klappt es bei den ersten paar Durchläufen und auf
einmal nicht mehr?

Muss ich das free() auf den char Pointer in dem Objekt oder auf das Objekt selbst anwenden?

Das Objekt erzeuge ich mit dem new Operator.
Sollte ich den Pointer mit free() und danach das Objekt mit delete freigeben?

Wo könnte sonst mein Problem liegen?


/edit
Man sieht vielleicht, dass ich nicht so viel mit Speicherzuweisungen am Hut habe.
Ich lese immer wieder von memset.
Was hat es damit auf sich?

Über Links auf Manuals o.ä. würde ich mich auch freuen.
Ich hab zu malloc noch nichts tiefergehendes gefunden.

Achso, nochwas - malloc soll einen NULL Pointer liefern, falls der Speicher nicht reserviert werden kann.
Das wollte ich prüfen, aber da bei der malloc Funktion selbst der Absturz kam, weiß ich leider nicht, was zurück gegeben werden würde.
 
Zuletzt bearbeitet:
Mit malloc kann einiges schief gehen. Zeig einfach mal einen kleinen
Ausschnitt aus dem Source wo der Fehler passiert.

Warum benutzt du malloc überhaupt? Du verwendest doch sowieso C++,
dann kannst du ja gleich new benutzten welches etwas einfacher zu
handeln ist.

Gruß,
Christian
 
Naja, die Klasse wurde mir mehr oder weniger aufgedrungen. War nicht immer mein Code.
C++ hab ich bislang immer so weit es geht, vermieden.. aber langsam komm ich wohl nicht mehr drum rum.

Der Konstruktor könnte nicht einfacher sein.
Hab den Code nicht hier, aber viel anders siehts nicht aus:
Code:
BufferKlasse::BufferKlasse(int bytesize)
{
    name = NULL;
    used = 0;
    pBuffer = (char *)malloc(bytesize)
};

Wie funktioniert der new Operator bei Typen wie "char *"?
Kann man da einfach "pBuffer = new char[bytesize];" schreiben?
 
Warum benutzt du malloc überhaupt?

Warum sollte er kein Malloc benutzen?
Nur weil es älter ist? Ein Unterschied zwischen Malloc und New gibt es IMHO nicht!

(Vielleicht belehrt mich ja jetzt jemand das ich Falsch liege. Das würde immerhin meinen Wissenshorizont erweitern ;-) )
 
Nein!
jetzt hab ich die Erklärung zu Memset vergessen:

- Sets buffers to a specified character -

Mit memset reservierst du keinen Speicher (!)
Du kannst (wie es ja oben steht) in einem buffer (z.B. char buffer[] ) die gewünschte Anzahl bytes mit einem beliebigen Zeichen ersetzten.
 
C++ hab ich bislang immer so weit es geht, vermieden
Du hast eine Klasse benutzt. Das ist schonmal ein Bestandteil von C++ :p

Bei new musst du nicht die bytes angeben !
New verwendet man so:
Code:
char* temp = new char[100]
Es sind jetzt dann wirklich 100 chars vorhanden.
Löschen tut man es einfach so:
Code:
delete[] temp

Alles ganz einfach.

Gruß, Christian
 
Hi.
mueslirocker hat gesagt.:
Naja, die Klasse wurde mir mehr oder weniger aufgedrungen. War nicht immer mein Code.
Hm. Warum verwendest nicht einfach std::string?
mueslirocker hat gesagt.:
Wie funktioniert der new Operator bei Typen wie "char *"?
Kann man da einfach "pBuffer = new char[bytesize];" schreiben?

Ja. Und dann mit
Code:
delete[] pBuffer;
wieder freigeben.

Gruß
 
@fhr:
Unterschiede new und malloc:

  • new ruft einen konstructor auf. macht malloc nicht !
  • delete ruft einen destructor auf. free nicht !
  • new kann überladen werden. (dann muss auch delete überladen werden)
  • new wirft eine excpetion "bad_alloc" wenn es keinen Speicher mehr gibt und terminiert nur, wenn diese nicht behandelt wird.
  • new liefert den richtigen Pointer. malloc muss gecastet werden, da es void* zurückgibt.
  • malloc kennt eine realloc funktion. Die gibts bei new nicht.
  • malloc möchte eine bytes*anzahl angabe. new reicht die anzahl.

Hoffe ich konnte deinen Horizont erweitern :-).

Gruß,
Christian
 
Erstmal danke für die ganzen Antworten. :)

fhr,
gut zu wissen, was memset ist.. könnt ich mal brauchen.

Mr.Undertaker,
ja, Klassen gehören zu C++, das war mir schon klar.
Die hab ich aber nicht geschrieben. :p
Ich muss damit nur auskommen.
Ich glaub Bytesize und Anzahl der Elemente spielt bei char keine Rolle.

deepthroat,
ich möchte eigentlich auch bei 'nem Char-Array bleiben, da ich den String durch mehrere Flex-(Teil-)Progamme jage und dafür schon den Input von Flex umgeschrieben habe (der wollte immer von FILE* lesen, jetzt macht er's von einem ausgewählten char* von mir)... naja, und da ich noch nie mit std::string gearbeitet hab.. aber das ist wohl das kleinere Problem.
Meine Klasse kann ich damit aber eh nicht ersetzen, da sie noch ein bisschen mehr kann.
Wenn ich den Absturz auf's Verrecken nicht beheben kann, werd ich darauf wohl zurück kommen.

Erstmal werd ich nun malloc mit new tauschen lassen und dann schau ich weiter.

Danke soweit. :)
 
<edit>Mist, hab auf Antworten, statt Edit geklickt</edit>

Also, ich bin ein Stück weiter... glaub ich.

Mein Problem ist immernoch, dass sich der Fehler bei kleinen Codeänderungen komplett verschieben kann, manchmal sogar ganz wegfällt.

Ich habe jetzt eine weitere Stelle eingegrenzt, bei der der Fehler auftaucht.
Und zwar kommt der Crash manchmal, wenn ich dem Buffer seinen Namen geben will.
buffer->name = strdup(seinName);
Wobei name anfangs auf NULL gesetzt wurde und seinName einen korrekten String beinhaltet (hab ich mir ausgeben lassen).
Auch wenn ich diese Zuweisung ersetze durch ein new gefolgt vom strcpy (ebenso mit malloc) kommt der Fehler. Zm strcpy kommt er dabei dann nichtmehr.
Ahso, malloc durch new ersetzen hat beim Konstruktor auch nicht geholfen. Der Fehler kommt dennoch.. manchmal.

Naja, aber egal ob durch dieses strdup, durch malloc oder durch new - es scheint durch Speicherzuweisungen ausgelöst zu werden.
Kann ich mir die Größe des dynamisch reservierten Speicher irgendwie ausgeben lassen? Am besten mit der oberen Grenze dazu?

Mich wundert das Ganze nur etwas, da meine Teststrings keine 50kbyte groß sind. Selbst wenn ich diese Strings 100 mal speichere, sollte da doch theoretisch kein Problem bei entstehen oder?

Habt ihr noch Ideen, woran es sonst liegen kann?
 
Zuletzt bearbeitet:
Zurück