2009-05-25 5 views
0

Hey alle, ich bekomme einen Haufen Korruption Fehler kann ich nicht herausfinden.Zuweisen und Freigeben eines Char * in C++

char * c = (char *) malloc(1); 
// main loop 
_gcvt_s(c, 100, ball->get_X_Direction(), 10); 
     if(pushFont(c, (SCREEN_WIDTH - 30), (SCREEN_HEIGHT - 40), message, screen, 
font, textColor) == false) 
     { 
      //return 1; // error rendering text. 
     } 
// end main loop 
free(c); 

Der obige Code ist die einzige Zeit, I c Zeiger verwenden, in _gcvt_s und pushFont(), die einfach ein char * als ersten Parameter übernimmt, und setzt den Text auf dem Bildschirm. Ansonsten benutze ich nicht c. Wenn ich versuche, c nach der Hauptschleife freizugeben (was ich glaube, dass ich das tun soll), bekomme ich eine Fehlermeldung, dass Visual Studio einen Fehler mit dem Heap (heap corruption) erfasst hat.

Kommentieren Sie den Aufruf von PushFont Ich erhalte immer noch den Fehler.

Kann mir jemand erklären, warum das Freigeben eines Zeichens (das 1 Byte, das ich auf dem Heap zugewiesen habe) mir einen Haufen Korruption geben würde?

Schließlich macht meine Hauptschleife eine Menge Sachen, ein Buddy und ich machen ein Pong-Spiel mit WinSocket, der Rest des Hauptkörpers ist die Schleife für das Spiel. Ich dachte nicht, dass es notwendig ist zu posten, aber ich werde meinen Beitrag mit der gesamten Hauptschleife aktualisieren, wenn es notwendig ist, aber ich glaube, ich bin gerade mit meinem Verständnis von malloc() und free().

Dank alle,

+0

sollten wir diese Frage nicht von "C++" auf "C" umstellen? –

Antwort

9

Verwendet nicht _gcvt_s den 2. Parameter wie die maximale Größe des zugewiesenen Puffer? Sie ordnen 1 Byte zu, aber sagen Sie _gcvt_s gibt es 100. Es schreibt glücklich bis zu 100 Bytes in den Puffer, der Ihren Haufen beschädigt. Dann stürzt das freie ab. Weisen Sie 100 Byte zu, wenn Sie möglicherweise auf 100 Byte zugreifen.

EDIT: Es klingt wie Sie müssen lernen, wie C speichert und manipuliert Strings. C speichert Strings als einzelne Bytes in zusammenhängenden Speicherausläufen, gefolgt von einem zusätzlichen Zeichen, um das Ende des Strings anzuzeigen. Dieses zusätzliche Zeichen hat einen ASCII-Wert von 0 (nicht das Zeichen '0', also ASCII 48). Wenn Sie also einen String wie "HALLO" haben, müssen Sie 6 Bytes speichern - einen für jeden der 5 Buchstaben und den Terminator.

Damit _gcvt_s() den Wert zu Ihrem Puffer zurückgibt, müssen Sie genügend Bytes für die Konvertierung und das zusätzliche abschließende Byte einschließen. Im Fall von _gcvt_s() werden Sie nach 10 Zeichen Genauigkeit gefragt. Sie müssen aber auch Platz für das Dezimalzeichen, das mögliche negative Vorzeichen, reservieren.

Gemäß dieser [Dokumentation] (http://msdn.microsoft.com/en-us/library/a2a85fh5(VS.80).aspx), gibt es eine #define in den Header für die maximal erforderliche Größe des Puffers. _CVTBUFSIZE Das Beispiel sollte man mit diesem Problem helfen

+0

Ich wollte nicht zwei Fragen in einem Beitrag stellen, aber ... Meine Frage, für den zweiten Parameter will es die Größe in Bytes des Puffers. Mit meinem Code wollte ich 10 Genauigkeit bei der Konvertierung. Mein Argument war, dass, wenn es die Anzahl der Bytes benötigt, die zum Speichern des konvertierten Zeichens benötigt werden, wenn jedes Zeichen 1 Byte ist, dann sollte ich 10 dort setzen. Error. Aus irgendeinem Grund versuchte ich 100 und es funktioniert, aber ich habe keine Ahnung, was der zweite Parameter verlangt. –

+2

Es ist ziemlich einfach - der zweite Parameter ist die Funktion _gcvt_s, die angibt, wie viele Bytes Sie im ersten Parameter im Puffer mit malloc zugewiesen haben. Sie lügen die Funktion, weil Sie nur ein Byte zugewiesen, nicht 100. Sie sollten 100 als erster Parameter an malloc übergeben - dies entspricht der Größe, die Sie gesagt haben, dass Sie zugewiesen –

+0

Ok, verstehe ich alles. Vielen Dank. Ich habe ein Follow-up, nur für mein Verständnis (Passieren von 100 Bytes scheint ziemlich unnötig). Warum funktioniert das Folgende nicht? _gcvt_s (c, 1, ball-> get_X_Direction(), 1); Ich habe 1 Byte zugewiesen, darüber habe ich nicht gelogen, und im 4. Parameter habe ich gesagt, dass ich nur 1 Byte Genauigkeit möchte. –

3

Warum brauchen Sie. den Heap zu verwenden Wenn alles, was Sie brauchen Platz für 1 Zeichen ist, kann nicht einfach in eine lokale Variable verwenden:?

char c; 
_gcvt_s(&c... 

+0

Wenn ich eine lokale Variable verwendet habe, erhielt ich einen Stapelfehler, wenn meine Hauptfunktion versucht sich zu entspannen (ich denke, was passiert ist, als ich den Fehler bekam, passiert es nie, bis ich das Programm schließe). –

+2

Nun, das wird passieren, wenn _gcvt_s mehr als 1 Zeichen mit dem Zeiger schreibt. In diesem Fall müssen Sie einen größeren Puffer übergeben. – PowerApp101

4

Gemäß der Dokumentation I _gcvt_s() nimmt einen Puffer und die Länge finden davon b wie die ersten beiden Argumente.

errno_t _gcvt_s( 
    char *buffer, 
    size_t sizeInBytes, 
    double value, 
    int digits 
); 

Ihr malloc() ed Puffer ist 1 Byte lang, sagen Sie _gcvt_s() es ist 100 Byte lang. Ich würde anfangen, hier zu suchen.

1

Sie benötigen mehr als ein Byte, um einen Float zu speichern. Weisen Sie eine praktischere Länge als 1 Byte zu ...

Sie brauchen auch wirklich nicht den Heap, versuchen Sie einen (etwas übergroßen) 16-Byte-Puffer und geben Sie _gcvt_s die richtige Pufferlänge (anstelle der magischen 100, die Sie es geben). Entmagrieren Sie Ihre Konstanten, während Sie dabei sind.

const unsigned int cuFloatStringLength = 16; 
const unsigned int cuFloatStringPrecision = 10; 

char c[cuFloatStringLength]; 

_gcvt_s(c, cuFloatStringLength, ball->get_X_Direction(), cuFloatStringPrecision); 

Das Problem sollte dann weg sein.

+0

Ok, das hat funktioniert. Außerdem habe ich die cuFloatStringLength auf 11 geändert, was die 10 Zeichen und den NULL-Terminator erlaubt. Error. 12 funktioniert ohne Fehler, aber 11 schlägt fehl. Weißt du, was das letzte Byte (12.) speichern würde? –

+0

Ist "cu" die ungarische Schreibweise für "Kupfer"? Zeigen Sie, dass Sie wirklich interessiert sind, und ordnen Sie Ihre Konstanten stattdessen aus "ag" oder "au". – bk1e

+0

Ich habe "Cu" für das vorherige Poster Beispiel verwendet. –