2009-05-25 5 views
0

Hey tout le monde, je reçois une erreur de tas de corruption, je ne peux pas comprendre.allouer et libérer un char * en 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); 

Le code ci-dessus est la seule fois que je l'utilise pointeur c, dans _gcvt_s et pushFont() qui accepte simplement un char * comme premier paramètre, et met le texte à l'écran. Autre alors que je n'utilise pas c. Lorsque j'essaie de libérer c après la boucle principale (ce que je pense que je suis censé faire), j'obtiens une erreur disant que Visual Studio a acquis une erreur avec le tas (corruption de tas).

Commentant l'appel à pushFont je reçois toujours l'erreur.

Quelqu'un peut-il m'expliquer pourquoi la libération d'un caractère (le 1 octet que j'ai alloué sur le tas) me donnerait un tas de corruption?

Enfin ma boucle principale fait beaucoup de choses, un pote et je fais un jeu de pong avec WinSocket, le reste du corps principal est la boucle pour le jeu. Je ne pensais pas qu'il était nécessaire de poster, mais je vais mettre à jour mon post avec la boucle principale entière si cela est nécessaire, mais je crois que je suis juste à côté de ma compréhension de malloc() et free().

Merci à tous,

+0

ne devrions-nous pas retag cette question de "C++" à "C"? –

Répondre

9

N'a pas _gcvt_s utiliser le 2ème paramètre comme la taille maximale du tampon alloué? Vous allouez 1 octet mais dites à _gcvt_s qu'il y en a 100. Donc, il écrit heureusement jusqu'à 100 octets dans la mémoire tampon corrompant votre tas. Puis les accidents gratuits. Allouer 100 octets si vous allez potentiellement accéder à 100 octets.

EDIT: Il semble que vous ayez besoin d'apprendre comment C stocke et manipule les chaînes. C stocke les chaînes sous forme d'octets individuels dans des suites contiguës de mémoire, suivies d'un caractère supplémentaire pour indiquer la fin de la chaîne. Ce caractère supplémentaire a une valeur ASCII de 0 (pas le caractère '0' qui est ASCII 48). Donc, si vous avez une chaîne comme "HELLO", il faut 6 octets pour stocker - un pour chacune des 5 lettres et le terminateur.

Pour que _gcvt_s() renvoie la valeur à votre tampon, vous devez inclure suffisamment d'octets pour la conversion et l'octet de fin supplémentaire. Dans le cas de _gcvt_s(), vous demandez 10 caractères de précision. Mais vous devez également réserver de la place pour la virgule décimale, le signe négatif potentiel.

Selon cette [documentation] (http://msdn.microsoft.com/en-us/library/a2a85fh5(VS.80).aspx), il y a un #define dans les en-têtes pour la taille maximale nécessaire du tampon:. _CVTBUFSIZE L'exemple, il devrait vous aider à ce problème

+0

Je ne voulais pas poser deux questions dans un seul article mais ... Ma question, pour le deuxième paramètre, il veut la taille en octets du tampon. Avec mon code je voulais 10 précision lors de la conversion. Mon raisonnement était que s'il veut le nombre d'octets nécessaires pour stocker le caractère converti, si chaque caractère est de 1 octet, alors je devrais mettre 10 là. Erreur. Pour une raison quelconque, j'ai essayé 100 et cela fonctionne, mais je n'ai aucune idée de ce que le deuxième paramètre demande. –

+2

C'est assez simple - le deuxième paramètre est de dire à la fonction _gcvt_s combien d'octets vous avez alloués (en utilisant malloc) dans le buffer du premier paramètre. Vous mentez à la fonction parce que vous avez alloué seulement un octet, pas 100. Vous devez passer 100 comme premier paramètre à malloc - cela correspondra à la taille que vous avez dit que vous avez attribué –

+0

Ok, je comprends tout cela. Merci beaucoup. J'ai un suivi, purement pour ma compréhension (passer 100 octets semble tout à fait inutile). Pourquoi ce qui suit ne fonctionne pas? _gcvt_s (c, 1, ball-> get_X_Direction(), 1); J'ai alloué 1 octet, je n'ai pas menti à ce sujet, et dans le 4ème paramètre, je lui ai dit que je voulais seulement 1 octet de précision. –

3

Pourquoi avez-vous besoin. d'utiliser le tas Si tout ce que vous avez besoin est un espace pour 1 car vous ne pouvez pas simplement utiliser une variable locale:?

char c; 
_gcvt_s(&c... 

+0

Lorsque j'ai utilisé une variable locale, j'ai reçu une erreur de corruption de pile lorsque ma fonction principale essaye de se dérouler (je pense que ce qui se passait quand j'ai eu l'erreur, ça n'arrive jamais avant de fermer le programme). –

+2

Eh bien, cela se produira si _gcvt_s écrit plus de 1 caractère en utilisant le pointeur. Dans ce cas, vous devez passer un tampon plus grand. – PowerApp101

4

Selon la documentation que je peux trouver _gcvt_s() prend un tampon et la longueur de ce b uffer comme les deux premiers arguments.

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

Votre tampon ed malloc() est 1 octet long, vous dites _gcvt_s() est de 100 octets. Je commencerais à chercher ici.

1

Vous avez besoin de plus d'un octet pour stocker un flotteur. Allouer une longueur plus pratique que 1 octet ...

Vous n'avez pas vraiment besoin du tas, essayez un tampon de 16 octets (légèrement surdimensionné) et donnez à _gcvt_s la bonne longueur de tampon (au lieu de la magie 100 que vous lui donnez). Dé-magie vos constantes pendant que vous y êtes.

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

char c[cuFloatStringLength]; 

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

Le problème devrait alors disparaître.

+0

Ok, cela a fonctionné. Aussi j'ai changé le cuFloatStringLength à 11 tenant compte des 10 caractères et du terminateur NULL. Erreur. 12 fonctionne sans erreurs, mais 11 échoue. Savez-vous ce que le dernier octet (12ème) serait stocké? –

+0

Est-ce que "cu" est la notation hongroise pour "copper"? Montrez-vous que vous vous souciez réellement de vos constantes et que vous les attribuez à partir de "ag" ou "au". – bk1e

+0

J'ai utilisé "cu" pour l'exemple des posters précédents. –