realloc() - da passt was nicht..



  • Hi,

    ich speichere mehrere daten hintereinander und weise daher Speicher dynamisch zu.

    Folgende Funktion habe ich mir dazu gebastelt:

    BYTE *bData;
    
    UINT CBinaryData::GetSize()
    {
    	if (bData != NULL)
    		// Gesamte Datengröße ermitteln:
    		return(_msize(bData));
    	else
    		return (0);
    }
    
    BYTE* CBinaryData::Allocate(UINT uSize)
    {
    	if (uSize > 0)
    	{
    		UINT uCurSize;
    
    		// Aktuelle Größe ermitteln:
    		uCurSize = GetSize();
    
    		if ((bData == NULL) && (uCurSize == 0))
    		{
    			// Größe reservieren für angeforderte Datengröße Reservieren:
    			bData = (BYTE*) malloc(uSize);
    
    			return (bData);
    		}
    		else if (uCurSize > 0)
    		{
    			BYTE *bTemp;
    
    			// Größe für angeforderte Datengröße erweitern:
    			bTemp = (BYTE*) realloc(bData, uCurSize + uSize);
    
    			if (bTemp != NULL)
    			{
    				// Pointer übernehmen:
    				bData = bTemp;
    
    				// Aktuelle Position zurückgeben:
    				return (bTemp + uCurSize);
    			}
    			else
    				// 'Alten' Speicher löschen:
    				ResetBinaryData();
    		}
    	}
    
    	return (NULL);
    }
    

    Jetzt tritt folgender Fehler auf:

    Jedes Mal wenn ich neue Daten an meine vorhandenen Daten anhängen möchte rufe ich meine Allocate()-Funktion auf. Anschließend schreibe ich die neuen Daten auf die Adresse die mir die Funktion zurück gibt.

    Aufruf 1. Es ist kein Speicher reserviert - malloc() reserviert Speicher
    Aufruf 2, 3, ... Es ist bereits Speicher reserviert - realloc() erweitert den zuvor reservierten Speicher

    Mir ist aufgefallen dass ich die ganze Funktionalität benutzen kann, wenn ich ein oder zwei Datensätze benutze.
    Sobald ich drei Datensätze benutze (also das zweite Mal realloc() verwende) habe ich ungültige werde in meinem Datensatz (Vermutlich zeigen die Pointer auf falsche Speicherbereiche).

    Was mache ich denn jetzt falsch?

    Gruß,
    Marco



  • Du bist erstmal im falschen Forum, damit fängt's an 🙄

    Please goto C++ 😉



  • Hat sich mittlerweile geklärt - lag nicht an dieser Funktion -.-

    Hab ich wieder nicht genug probiert vorm posten 😉



  • Dieser Thread wurde von Moderator/in rüdiger aus dem Forum ANSI C in das Forum C++ verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Wieso nimmst Du nicht new/delete, dann kannst Du Dir auch das Pointercasting sparen, das unter C quasi als Todsünde geahndet wird?

    C != C++;
    

    😉



  • Mit new / delete bin ich zu sehr eingeschränkt.
    Ich muss dynamisch immer unterschiedlich viel speicher reservieren. Das geht auf diese Weise viel besser.

    Das mit dem Casting sehe ich nicht so eng 😉



  • Red Skall schrieb:

    Mit new / delete bin ich zu sehr eingeschränkt.

    Kaum eingeschränkter als mit new und delete. realloc() mach in den meisten Fällen nichts anderes als malloc(), memcpy(), free() - außer es kann ausnahmsweise doch mal den ursprünglichen Speicherbereich vergrößern.



  • Mir geht es darum den Bereich zu vergrößern. Oder verstehe ich da was falsch 😕 😉



  • Red Skall schrieb:

    Oder verstehe ich da was falsch 😕 😉

    Ja scheinbar. realloc kann ja nicht garantieren dass noch genug Platz ist, um den Bereich einfach so zu vergrößern. Falls kein Platz ist, nimmt realloc einen komplett neuen Bereich und kopiert den Kram aus dem alten Bereich da rein und gibt danach den alten Bereich frei. Und das ist eher die Regel als die Ausnahme.



  • Wäre es möglich, intern std::vector aus der Standard Template Library zu benutzen, oder ist das zu High-Level? Der reserviert immer ein bisschen mehr Speicher als benötigt, somit kannst du in den meisten Fällen Elemente anhängen, ohne den Speicherbereich neu anfordern zu müssen.

    Und jetzt bin ich noch nicht auf die anderen Vorteile wie Aufruf einer einzigen Methode, Minimierung des Gefrickels und der damit verbundenen Fehleranfälligkeit, Erhöhung der Wartbarkeit, Debug-Unterstützung durch Assertions, Generizität und leichte Austauschbarkeit mit anderen Containern oder Elementtypen eingegangen...



  • Ich weis, dass realloc den Bereich meistens verschiebt, aber das ist ok.

    Hauptsache, es wird neuer Speicher reserviert. Mehr will ich ja garnicht.
    Der Fehler lag an nem anderen Programmteil, die Funktion funktioniert so wie sie soll.

    Gruß



  • pumuckl schrieb:

    ...Falls kein Platz ist, nimmt realloc einen komplett neuen Bereich und kopiert den Kram aus dem alten Bereich da rein und gibt danach den alten Bereich frei. Und das ist eher die Regel als die Ausnahme.

    Kann ich so nicht ganz bestätigen, was aber keine Rolle spielt, weil realloc() genau dann das Kopieren anfangen wird, wenn man's absolut nicht brauchen kann, man kann's ja nicht steuern 😞 . Bei Realtime- Problemen also generell Finger weg vom Heap, immer über statische Arrays buffern, schadet auch bei "normalen Programmen" nicht, verbessert i.d.R. das Laufzeitverhalten.
    😉



  • pointercrash() schrieb:

    [...] weil realloc() genau dann das Kopieren anfangen wird, wenn man's absolut nicht brauchen kann, man kann's ja nicht steuern 😞 . Bei Realtime- Problemen also generell Finger weg vom Heap, immer über statische Arrays buffern, schadet auch bei "normalen Programmen" nicht, verbessert i.d.R. das Laufzeitverhalten.

    Wieder ein Grund für die STL. Wenn man std::vector einsetzt, kann man mittels reserve() sicherstellen, dass genügend Speicher vorhanden ist. Bei einer std::deque sind Reallokationen weniger schlimm, da es sich nur um Teilbereiche handelt, bei einer std::list werden sogar einzelne Elemente angefordert.

    Abgesehen davon ist der Stack nicht wirklich eine Lösung, da dessen Speicher sehr begrenzt ist und die Dimension von statischen Arrays zur Compilezeit feststehen muss.

    Red Skall, hast du meinen letzten Beitrag noch gelesen? Ich glaube, du hast deinen nämlich gerade abgeschickt, bevor du meinen gesehen hast... 😉



  • Nexus schrieb:

    Abgesehen davon ist der Stack nicht wirklich eine Lösung, da dessen Speicher sehr begrenzt ist und die Dimension von statischen Arrays zur Compilezeit feststehen muss.

    Der Ur- Post stand im ANSI-C- Forum und das realloc() ist eine <cstdlib>- Geschichte. In Ermangelung einer STL habe ich "C- stylish" geantwortet und da wirken statische Buffer oft Wunder.
    Sinnvoll dimensionierte Buffer sparen viel Rechenzeit, die ansonsten zur Laufzeit der Heapverwaltung aufgebürdet würde. 😉



  • @Nexus: Jo, habs gerade gelesen 😉

    Aber mit Vektoren kenne ich mich nicht so aus 😉
    Ich finde so wie ich das gemacht habe ist das ganz gut gelöst.

    Das mit der Rechenzeit die während der dynamischen Erzeugung benötigt wird stimmt natürlich!


  • Administrator

    Red Skall schrieb:

    Aber mit Vektoren kenne ich mich nicht so aus 😉

    Dann wird es aber dringend Zeit, dies zu lernen. Die Standardbibliothek ist ein wesentlicher Bestandteil von C++.

    Grüssli



  • pointercrash() schrieb:

    Sinnvoll dimensionierte Buffer sparen viel Rechenzeit, die ansonsten zur Laufzeit der Heapverwaltung aufgebürdet würde

    absolut richtig. in vielen fällen ist die dynamik, die malloc und ähnliche lösungen bieten, gar nicht nötig und sorgt nur für schlechtes laufzeitverhalten.



  • pointercrash() schrieb:

    Nexus schrieb:

    Abgesehen davon ist der Stack nicht wirklich eine Lösung, da dessen Speicher sehr begrenzt ist und die Dimension von statischen Arrays zur Compilezeit feststehen muss.

    Der Ur- Post stand im ANSI-C- Forum und das realloc() ist eine <cstdlib>- Geschichte. In Ermangelung einer STL habe ich "C- stylish" geantwortet und da wirken statische Buffer oft Wunder.

    Ich verstehe den Zusammenhang zu meinem Quote nicht ganz - was ich gesagt habe, gilt genauso für C. Klar können statische Arrays auch sinnvoll sein, das bestreite ich gar nicht. Aber das hat dann nichts mehr mit realloc() oder der STL zu tun. Performance beim Stack zwar ein Vorteil, aber man sollte nicht vergessen, dass man dabei auch Flexibilität verliert. Und nicht immer ist Performance das Entscheidende. Deshalb finde ich den folgenden Satz von dir zu radikal.

    pointercrash() schrieb:

    Bei Realtime- Problemen also generell Finger weg vom Heap, immer über statische Arrays buffern, schadet auch bei "normalen Programmen" nicht, verbessert i.d.R. das Laufzeitverhalten.

    Red Skall schrieb:

    Aber mit Vektoren kenne ich mich nicht so aus 😉
    Ich finde so wie ich das gemacht habe ist das ganz gut gelöst.

    Ich würde auch meinen, dass du das mal anschauen solltest. Zumindest würde ich von niemandem sagen, er beherrsche C++, solange er sich nicht mit der Standardbibliothek (und der STL) auskennt... 😉

    Die STL bietet einem wirklich sehr viel Komfort und Freiheit. Zudem ist es auch sehr gut möglich, dass ein besseres Laufzeitverhalten erzielt wird, da die Container oft eine relativ intelligente Speicherverwaltung mit sich bringen. Mit der Möglichkeit, Container auszutauschen und selber noch herumzuexperimentieren, erreicht man dann erst das volle Potenzial. Von der besseren Wartbarkeit, Sicherheit (Speicherfehler, Memory Leaks, gute Assertions) und Übersichtlichkeit ganz zu schweigen.

    Einführende Artikel in die Standard Template Library findest du hier. Glaub mir, das ist einen Blick wert. 🙂



  • Danke für den Link, hab gerade überflogen. Das schaue ich mir auf jeden Fall nochmal genau an.



  • Was realloc() und die (nicht wirklich vorhandenen) C++-Äquivalente angeht gibts auch eine angeregte Diskussion auf comp.lang.c++.moderated:

    http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/b2bfadcc9efa3ba1#


Log in to reply