2011-10-15 9 views
4

Je suis assez nouveau à C alors s'il vous plaît supporter mon incompétence. Je veux lire un fichier entier Executable dans un tampon:C allocation de mémoire tampon

#include <stdlib.h> 
FILE *file = fopen(argv[1], "rb"); 
long lSize; 

fseek(file, 0, SEEK_END); 
lSize = ftell(file); 
fseek(file, 0, SEEK_SET); 

char *buffer = (char*) malloc(sizeof(char)*lSize); 
fread(buffer, 1, lSize, file); 

Le fichier a 6144 octets (stockés correctement dans lSize), mais la taille de mon mémoire tampon est seulement 4 octets, donc que la signature MZ est stocké dans le tampon.

Pourquoi malloc n'attribue-t-il que 4 octets dans ce cas?

Édition: Probablement le tampon char est terminé par le premier 0 dans l'en-tête MZ du fichier PE. Si je mets le tampon à une certaine valeur cependant, le fichier entier sera stocké. Si je mets le tampon à int (= 4 octets), le buffer ne sera pas terminé mais sera bien sûr plus grand (vs char = 1 byte). Je veux juste copier l'octet de fichier pour byte avec les octets nuls aussi bien.

Edit 2: Le tampon contient bien sûr tout ce qu'il faut, mais si je tente de l'écrire dans un nouveau fichier avec fwrite, il n'écrit au premier \ 0 (ce qui est de 4 octets). Je viens de me tromper. Correction de ceci Désolé, le problème n'était pas assez bien défini.

+0

Pourquoi pensez-vous que malloca alloue 4 octets seulement? –

+1

Comment savez-vous qu'il alloue seulement 4 octets (il ne devrait pas, et je ne vois pas d'erreur dans votre code). Comment déterminez-vous que seulement 4 octets ont été lus/stockés? – Mat

+0

Vous n'avez pas besoin d'utiliser sizeof pour connaître la taille du caractère. sizeof (char) est toujours 1. En C, "char" et "byte" sont synonymes. – tiftik

Répondre

7

Si lSize est vraiment égal à 6144 alors votre code allouera en effet 6144 octets, puis de lire tout le contenu du fichier. Si vous croyez que seulement 4 octets sont lus, c'est probablement parce que le 5ème octet est un zéro. Ainsi, lorsque le tampon est interprété comme une chaîne terminée par zéro, il se termine à ce point.

Vous pouvez inspecter le reste de votre tampon en regardant buffer[4], buffer[5], etc.

En aparté, vous n'avez pas besoin de lancer le retour de malloc et sizeof(char) == 1 par définition. La meilleure pratique consiste à écrire le malloc comme ceci:

char *buffer = malloc(lSize); 

Mais cela ne changera pas vos résultats.

+0

Je pense que vous pourriez avoir raison. L'en-tête DOS est \ MZ220 et donc terminé. Mais si je mets manuellement le tampon à un grand nombre, par ex. buffer [16000] le tampon contiendra le fichier entier indépendamment du 0. – Laughingman

+0

Je parierais que vous regardez tampon comme une chaîne terminée par le zéro dans le débogueur. L'utilisation de printf s'arrêtera à 0. Si seulement 4 octets ont été attribués, vous feriez probablement erreur sur la puce. Exécutez une boucle for et imprimez le tampon char par char, 'printf ("% c \ n ", tampon [i]);' –

+0

Je ne comprends pas votre modification. Votre code actuel lit le fichier entier dans le tampon. C'est déjà tout là. Mais vous ne pouvez pas le traiter comme une chaîne terminée par un caractère nul. –

3

Pourquoi malloc n'attribue-t-il que 4 octets dans ce cas?

Parce que vous ne avez pas #include <stdlib.h> (et jette la valeur de retour de malloc()).


Ne pas oublier de #include <stdlib.h> afin que le compilateur sait malloc renvoie une valeur de type void* (plutôt que de supposer qu'il retourne un int) et prend un argument de size_t de type (plutôt que asuuming est un int

De même, ne pas utiliser la valeur de retour de malloc. Une valeur de type void* peut être affectée à un objet de type pointeur (à tout type). La conversion de la valeur de retour fait que le compilateur convertit silencieusement int (supposé lorsque <stdlib.h> n'était pas inclus) au type dans la distribution. Notez que le compilateur se plaindrait sans que le casting ne vous laisse savoir que vous aviez oublié l'include.


L'erreur réelle n'est pas malloc allouer un montant erroné (je crois qu'il affectera le montant exact de toute façon). La véritable erreur est de supposer que malloc renvoie un int lorsqu'il renvoie un void *.int et void* peut être passé différemment (un dans un registre, l'autre sur la pile par exemple) ou ils ont des représentations différentes (deux le complément de pour int et adresse segmentée pour void*) ou toute autre chose (très probablement sizeof (int) != sizeof (void*)).

+3

Huh? Êtes-vous sûr de cela? –

+3

Sure casting la valeur de retour de malloc est une mauvaise pratique, mais une erreur? J'en doute, comme je l'ai fait cent mille fois (à partir d'un arrière-plan C++, où il n'est pas implicitement converti). –

+1

pourquoi le moulage devrait être un problème? – akappa

1

comment vérifiez-vous la taille du tampon, faites-vous un sizeof(buffer)? Dans ce cas, vous ne voyez que la taille d'un pointer to int qui est de 4 octets. Vous ne pouvez pas obtenir la taille d'un tampon hors de son pointeur. Vous devez le stocker séparément comme vous l'avez fait (au lSize).

Si malloc() n'a pas renvoyé NULL alors votre tampon est correct et la taille est correcte.