Progtwigción C: malloc () dentro de otra función

Necesito ayuda con malloc() dentro de otra función .

Estoy pasando un puntero y un tamaño a la función desde mi main() y me gustaría asignar memoria para ese puntero dinámicamente usando malloc() desde dentro de esa función llamada, pero lo que veo es que … la memoria, que se está asignando, es para el puntero declarado dentro de la función llamada y no para el puntero que está dentro de main() .

¿Cómo debo pasar un puntero a una función y asignar memoria para el puntero pasado desde dentro de la función llamada ?


He escrito el siguiente código y obtengo el resultado como se muestra a continuación.

FUENTE:

 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; } 

SALIDA DEL PROGRAMA:

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

Debe pasar un puntero a un puntero como parámetro de su función.

 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; } 

¿Cómo debo pasar un puntero a una función y asignar memoria para el puntero pasado desde dentro de la función llamada?

Pregúntate esto: si tuvieras que escribir una función que tuviera que devolver un int , ¿cómo lo harías?

Lo devolverías directamente:

 int foo(void) { return 42; } 

o devolverlo a través de un parámetro de salida agregando un nivel de indirección (es decir, utilizando un int* lugar de int ):

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

Por lo tanto, cuando devuelve un tipo de puntero ( T* ), es lo mismo: devuelve el tipo de puntero directamente:

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

o agrega un nivel de direccionamiento indirecto:

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

Si desea que su función modifique el puntero, deberá pasarlo como un puntero a un puntero. Aquí hay un ejemplo simplificado:

 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); } 

alloc_pixels pasar el puntero por referencia , no por copia , el parámetro en la función alloc_pixels requiere el signo & y volver a pasar la dirección del puntero, es decir, llamar por referencia en C hablar.

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

    if (alloc_pixels (& input_image, bmp_image_size) == NULL)
      printf ("\ nPoint2: memoria asignada:% d bytes", _ msize (input_image));
    más
      printf ("\ nPunto3: memoria no asignada");     

 }

 firmado char alloc_pixels (unsigned char ** ptr, unsigned int size)
 {
     estado de char firmado = NO_ERROR;
     * ptr = NULL;

     * ptr = (char sin signo *) malloc (tamaño);

     if ((* ptr) == NULL)
     {
         estado = ERROR;
         / * gratis (ptr);
         printf ("\ nERROR: la asignación de memoria no se completó correctamente");  * /
     }

     printf ("\ nPunto1: memoria asignada:% d bytes", _ msize (* ptr));

     estado de devolución;
 }

He comentado las dos líneas free(ptr) y “ERROR: …” dentro de la función alloc_pixels ya que eso es confuso. No necesita free un puntero si la asignación de memoria falló.

Editar: Después de mirar el enlace msdn proporcionado por OP, una sugerencia, el ejemplo de código es el mismo que el anterior en mi respuesta … pero … cambie el especificador de formato a %u para el tipo size_t , en el printf(...) llamar a main() .

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

    if (alloc_pixels (& input_image, bmp_image_size) == NULL)
      printf ("\ nPunto2: memoria asignada:% u bytes", _ msize (input_image));
    más
      printf ("\ nPunto3: memoria no asignada");     

 }

Esto no tiene sentido :

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

alloc_pixels devuelve un signed char ( ERROR o NO_ERROR ) y lo compara con NULL (que se supone que se usa para los punteros).

Si desea que se input_image , debe pasarle un puntero a alloc_pixels . alloc_pixels firma alloc_pixels sería la siguiente:

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

Lo llamarías así:

 alloc_pixels(&input_image, bmp_image_size); 

Y la asignación de memoria

 *ptr = malloc(size); 

En su código inicial, cuando pasaba input_image a la función alloc_pixels, el comstackdor creaba una copia (es decir, ptr) y almacenaba el valor en la stack. Usted asigna el valor devuelto por malloc a ptr. Este valor se pierde una vez que la función retorna a main y la stack se desenrolla. Por lo tanto, la memoria todavía se asigna en el montón, pero la ubicación de la memoria nunca se almacenó en (o se asignó a) la imagen de entrada, de ahí el problema.

Puede cambiar la firma de la función alloc_pixels que sería más simple de entender, y no requerirá la variable de ‘estado’ adicional también.

 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; } 

Puede llamar a la función anterior en main:

 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; } 

La asignación de parámetros funcionará solo si establece el valor en su dirección .

Hay 2 puntos que debe saber antes de intentar resolver este problema:
1. Función C : todos los parámetros que pasó a la función serán una copia en la función.

Eso significa que cada tarea que hayas realizado en la función no afectará las variables que se encuentran fuera de la función, en realidad estás trabajando en la copia :

 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 

Entonces, si quiere cambiar i en la función, necesita saber la diferencia entre la cosa y su copia:

La copia compartió el valor con la cosa, pero no la dirección .

Y esa es su única diferencia.

Entonces la única manera de cambiar i en la función es usando la dirección de i.

Por ejemplo, hay una nueva función fun_addr:

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

De esta manera, podrías cambiar el valor de i.

  1. malloc :

El punto clave en la función fun_addr es que pasaste una dirección a la función. Y podría cambiar el valor almacenado en esa dirección.

¿Qué hará malloc?

malloc asignará un nuevo espacio de memoria y devolverá el puntero apuntando a esa dirección .

Mire esta instrucción:

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

Lo que está haciendo es dejar que el valor de array sea igual a la dirección devuelta por malloc.

¿Ver? Esta es la misma pregunta, asignando permanentemente valor al parámetro pasado a la función. En este punto, el valor es address .

Ahora, asigne la dirección (devuelta por malloc) a la dirección (almacena la dirección anterior).

Entonces el código debería ser:

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

Este funcionará.

La única forma en que podía hacer que el puntero a una solución de puntero funcionara para un problema similar que tenía para esta función

  BOOL OpenBitmap2 ( LPCTSTR pszFileName, char** pszBMPFile) 

Fue mediante la asignación de un puntero temporal para almacenar la dirección

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

luego reasignándolo

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

Cualquier comentario sobre por qué usar “* pszBMPFile” directamente con GlobalAlloc no funcionó sería apreciado. Respondí mi propia pregunta. Olvidé llevar el “*” a través de pszBMPFile en las otras líneas de código. Buenas lecciones de todos los contribuyentes. Muchas gracias.