C Programmation: malloc () dans une autre fonction

J’ai besoin d’aide avec malloc() dans une autre fonction .

Je passe un pointeur et une taille à la fonction de mon main() et je voudrais allouer de la mémoire pour ce pointeur dynamicment en utilisant malloc() à l’intérieur de la fonction appelée, mais ce que je vois c’est que … la mémoire, qui est alloué, est pour le pointeur déclaré dans ma fonction appelée et non pour le pointeur qui est à l’intérieur de main() .

Comment passer un pointeur sur une fonction et allouer de la mémoire pour le pointeur passé de la fonction appelée ?


J’ai écrit le code suivant et je reçois la sortie comme indiqué ci-dessous.

LA SOURCE:

 int main() { unsigned char *input_image; unsigned int bmp_image_size = 262144; if(alloc_pixels(input_image, bmp_image_size)==NULL) printf("\nPoint2: Memory allocated: %d bytes",_msize(input_image)); else printf("\nPoint3: Memory not allocated"); return 0; } signed char alloc_pixels(unsigned char *ptr, unsigned int size) { signed char status = NO_ERROR; ptr = NULL; ptr = (unsigned char*)malloc(size); if(ptr== NULL) { status = ERROR; free(ptr); printf("\nERROR: Memory allocation did not complete successfully!"); } printf("\nPoint1: Memory allocated: %d bytes",_msize(ptr)); return status; } 

SORTIE PROGRAMME:

 Point1: Memory allocated ptr: 262144 bytes Point2: Memory allocated input_image: 0 bytes 

Vous devez passer un pointeur sur un pointeur comme paramètre de votre fonction.

 int main() { unsigned char *input_image; unsigned int bmp_image_size = 262144; if(alloc_pixels(&input_image, bmp_image_size) == NO_ERROR) printf("\nPoint2: Memory allocated: %d bytes",_msize(input_image)); else printf("\nPoint3: Memory not allocated"); return 0; } signed char alloc_pixels(unsigned char **ptr, unsigned int size) { signed char status = NO_ERROR; *ptr = NULL; *ptr = (unsigned char*)malloc(size); if(*ptr== NULL) { status = ERROR; free(*ptr); /* this line is completely redundant */ printf("\nERROR: Memory allocation did not complete successfully!"); } printf("\nPoint1: Memory allocated: %d bytes",_msize(*ptr)); return status; } 

Comment passer un pointeur sur une fonction et allouer de la mémoire pour le pointeur passé de la fonction appelée?

Demandez-vous ceci: si vous deviez écrire une fonction qui devait renvoyer un int , comment le feriez-vous?

Vous pouvez soit le retourner directement:

 int foo(void) { return 42; } 

ou le renvoyer via un paramètre de sortie en ajoutant un niveau d’ indirection (c’est-à-dire en utilisant un int* au lieu de int ):

 void foo(int* out) { assert(out != NULL); *out = 42; } 

Donc, quand vous retournez un type de pointeur ( T* ), c’est la même chose: soit vous retournez le type de pointeur directement:

 T* foo(void) { T* p = malloc(...); return p; } 

ou vous ajoutez un niveau d’indirection:

 void foo(T** out) { assert(out != NULL); *out = malloc(...); } 

Si vous souhaitez que votre fonction modifie le pointeur lui-même, vous devez le passer en tant que pointeur sur un pointeur. Voici un exemple simplifié:

 void allocate_memory(char **ptr, size_t size) { void *memory = malloc(size); if (memory == NULL) { // ...error handling (btw, there's no need to call free() on a null pointer. It doesn't do anything.) } *ptr = (char *)memory; } int main() { char *data; allocate_memory(&data, 16); } 

Vous devez passer le pointeur par référence , et non par copie , le paramètre dans la fonction alloc_pixels nécessite que l’esperluette & alloc_pixels l’adresse du pointeur – c’est-à-dire l’ appel par référence dans C speak.

 principale()
 {
    unsigned char * input_image;
    unsigned int bmp_image_size = 262144;

    if (alloc_pixels (& input_image, bmp_image_size) == NULL)
      printf ("\ nPoint2: mémoire allouée:% d octets", _ msize (input_image));
    autre
      printf ("\ nPoint3: mémoire non allouée");     

 }

 signé char alloc_pixels (unsigned char ** ptr, unsigned int size)
 {
     signé char status = NO_ERROR;
     * ptr = NULL;

     * ptr = (char non signé *) malloc (taille);

     if ((* ptr) == NULL)
     {
         status = ERREUR;
         / * gratuit (ptr);
         printf ("\ nERROR: l'allocation de mémoire ne s'est pas terminée correctement!");  * /
     }

     printf ("\ nPoint1: mémoire allouée:% d octets", _ msize (* ptr));

     statut de retour;
 }

J’ai commenté les deux lignes free(ptr) et “ERROR: …” dans la fonction alloc_pixels car cela est déroutant. Vous n’avez pas besoin de free un pointeur si l’allocation de mémoire a échoué.

Edit: Après avoir examiné le lien msdn fourni par OP, une suggestion, l’exemple de code est le même que précédemment dans ma réponse … mais … changez le spécificateur de format en %u pour le type size_t , dans printf(...) appelle dans main() .

 principale()
 {
    unsigned char * input_image;
    unsigned int bmp_image_size = 262144;

    if (alloc_pixels (& input_image, bmp_image_size) == NULL)
      printf ("\ nPoint2: mémoire allouée:% u octets", _ msize (input_image));
    autre
      printf ("\ nPoint3: mémoire non allouée");     

 }

Cela n’a pas de sens :

 if(alloc_pixels(input_image, bmp_image_size)==NULL) 

alloc_pixels renvoie un caractère signed char ( ERROR ou NO_ERROR ) et vous le comparez à NULL (qui est censé être utilisé pour les pointeurs).

Si vous souhaitez que input_image soit modifié, vous devez lui transmettre un pointeur vers alloc_pixels . alloc_pixels signature alloc_pixels serait la suivante:

 signed char alloc_pixels(unsigned char **ptr, unsigned int size) 

Vous appelez ça comme ça:

 alloc_pixels(&input_image, bmp_image_size); 

Et l’allocation de mémoire

 *ptr = malloc(size); 

Dans votre code initial, lorsque vous passiez input_image à la fonction alloc_pixels, le compilateur en créait une copie (c.-à-d. Ptr) et stockait la valeur sur la stack. Vous atsortingbuez la valeur renvoyée par malloc à ptr. Cette valeur est perdue une fois que la fonction retourne à main et que la stack se déroule. Ainsi, la mémoire est toujours allouée sur le tas mais l’emplacement de la mémoire n’a jamais été stocké dans (ou assigné à) input_image, d’où le problème.

Vous pouvez changer la signature de la fonction alloc_pixels qui serait plus simple à comprendre, et vous n’aurez pas besoin de la variable supplémentaire «status».

 unsigned char *alloc_pixels(unsigned int size) { unsigned char *ptr = NULL; ptr = (unsigned char *)malloc(size); if (ptr != NULL) printf("\nPoint1: Memory allocated: %d bytes",_msize(ptr)); return ptr; } 

Vous pouvez appeler la fonction ci-dessus en principal:

 int main() { unsigned char *input_image; unsigned int bmp_image_size = 262144; if((input_image = alloc_pixels(bmp_image_size))==NULL) printf("\nPoint3: Memory not allocated"); else printf("\nPoint2: Memory allocated: %d bytes",_msize(input_image)); return 0; } 

L’affectation des parameters ne fonctionnera que si vous définissez la valeur sur son adresse .

Vous devez savoir 2 points avant de tenter de résoudre ce problème:
1. C Fonction : Tous les parameters que vous avez passés à la fonction seront une copie dans la fonction.

Cela signifie que chaque tâche que vous avez effectuée dans la fonction n’affecte pas les variables extérieures à la fonction, vous travaillez actuellement sur la copie :

 int i = 1; fun(i); printf("%d\n", i); //no matter what kind of changes you've made to i in fun, i's value will be 1 

Donc, si vous voulez changer i dans la fonction, vous devez connaître la différence entre la chose et sa copie:

La copie a partagé la valeur avec la chose, mais pas l’ adresse .

Et c’est leur seule différence.

Donc, la seule façon de changer i dans la fonction est d’utiliser l’adresse de i.

Par exemple, il y a une nouvelle fonction fun_addr:

 void fun_addr(int *i) { *i = some_value; } 

De cette façon, vous pouvez changer la valeur de i.

  1. malloc :

Le point clé de la fonction fun_addr est que vous avez passé une adresse à la fonction. Et vous pouvez changer la valeur stockée dans cette adresse.

Que va faire malloc?

malloc allouera un nouvel espace mémoire et renverra le pointeur sur cette adresse .

Regardez cette instruction:

 int *array = (int*) malloc(sizeof(int) * SIZE); 

Ce que vous faites est de laisser la valeur du tableau égale à l’adresse renvoyée par malloc.

Voir? C’est la même question, en atsortingbuant une valeur permanente au paramètre passé à la fonction. À ce stade, la valeur est address .

Maintenant, atsortingbuez l’adresse (renvoyée par malloc) à l’adresse (stocke l’ancienne adresse).

Le code devrait donc être:

 void fun_addr_addr(int **p) { *p = (int*) malloc(sizeof(int) * SIZE); } 

Celui-ci fonctionnera.

Le seul moyen d’obtenir un pointeur vers une solution de pointeur pour un problème similaire que j’avais pour cette fonction

  BOOL OpenBitmap2 ( LPCTSTR pszFileName, char** pszBMPFile) 

Était en affectant un pointeur temporaire pour stocker l’adresse

  char* BMPFile; { BMPFile = (char*)GlobalAlloc(GPTR, dwFileSize + 1); // allocate storage using GlobalAlloc + 1 for null term ssortingng 

puis le réassigner

  {* pszBMPFile = BMPFile; return (0);} // Error = False 

Tout commentaire sur l’utilisation directe de “* pszBMPFile” avec GlobalAlloc serait apprécié. J’ai répondu à ma propre question. J’ai oublié de porter le “*” avec pszBMPFile dans les autres lignes de code. Bonnes leçons de tous les consortingbuteurs. Merci beaucoup.