C编程:另一个函数里面的malloc()

时间:2010-05-14 22:29:05

标签: c function pointers malloc

我需要帮助其他功能 中的malloc()

我将指针 size 传递给我main()的函数,我想使用{{1}为该指针动态分配内存从那个被调用的函数里面,但是我看到的是......被分配的内存是在我调用的函数中声明的指针而不是malloc()内的指针。

我应该如何传递指向函数的指针并为被调用函数内部传递的指针分配内存


我编写了以下代码,输出如下所示。

来源:

main()

计划输出:

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

9 个答案:

答案 0 :(得分:88)

  

我应该如何将指针传递给   功能和分配内存   从被调用的内部传递指针   功能

问问自己:如果你必须编写一个必须返回int的函数,你会怎么做?

你要么直接归还:

int foo(void)
{
    return 42;
}

或通过添加indirection级别(即使用int*而非int)将其返回到输出参数:

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

所以当你返回一个指针类型(T*)时,它是一样的:你要么直接返回指针类型:

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

或者你添加一个间接级别:

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

答案 1 :(得分:69)

您需要将指针作为函数的参数传递给指针。

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

答案 2 :(得分:8)

如果希望函数修改指针本身,则需要将其作为指针传递给指针。这是一个简化的例子:

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

答案 3 :(得分:3)

您需要通过引用传递指针,而不是通过复制传递,函数alloc_pixels中的参数需要&符号&传回指针的地址 - 在C语言中通过引用调用

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

}

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

我已在free(ptr)函数中注释掉了alloc_pixels和“ERROR:...”两行,因为这令人困惑。如果内存分配失败,则不需要free指针。

编辑:在查看OP提供的msdn链接后,建议,代码示例与我之前的答案相同....但是...更改在%u的{​​{1}}调用中,size_t类型的格式说明符为printf(...)

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

   if(alloc_pixels(&input_image, bmp_image_size)==NULL)
     printf("\nPoint2: Memory allocated: %u bytes",_msize(input_image));
   else
     printf("\nPoint3: Memory not allocated");     

}

答案 4 :(得分:2)

这没有意义:

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

alloc_pixels返回signed charERRORNO_ERROR)并将其与NULL(应该用于指针)进行比较。< / p>

如果您想要更改input_image,则需要将指针传递给alloc_pixelsalloc_pixels签名如下:

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

你会这样称呼:

alloc_pixels(&input_image, bmp_image_size);

内存分配

*ptr = malloc(size);

答案 5 :(得分:1)

在初始代码中,当您将input_image传递给函数alloc_pixels时,编译器正在创建它的副本(即ptr)并将值存储在堆栈中。您将malloc返回的值分配给ptr。一旦函数返回main并且堆栈展开,该值就会丢失。因此,内存仍然在堆上分配,但内存位置从未存储在(或分配给)input_image中,因此存在问题。

你可以更改alloc_pixels函数的签名,这个签名更容易理解,你也不需要额外的'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;
}

您可以在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;

}

答案 6 :(得分:1)

  

参数的分配仅在您将值设置为地址时才有效。

在尝试解决此问题之前,您应该知道2点:
1. C函数:传递给函数的所有参数都将是函数中的副本。

这意味着您在函数中进行的每个赋值都不会影响函数外部的变量,您实际上正在处理副本

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

所以,如果你想在函数中改变i,你需要知道这个东西和它的副本之间的区别:

  

副本与地址共享,而不是地址

这是他们唯一的区别。

因此,在函数中更改i的唯一方法是使用i的地址。

例如,有一个新功能fun_addr:

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

通过这种方式,你可以改变我的价值。

  1. malloc
  2. fun_addr函数的关键点是,您已将地址传递给函数。您可以更改存储在该地址中的值。

    malloc会做什么?

    malloc将分配一个新的内存空间,返回指向该地址的指针

    看看这条指令:

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

    你正在做的是让数组的值等于malloc返回的地址。

    请参阅?这是同样的问题,永久地为传递给函数的参数赋值。此时,值为address

      

    现在,将地址(由malloc返回)分配给地址(存储旧地址)。

    所以代码应该是:

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

    这个会起作用。

答案 7 :(得分:1)

我唯一可以获得指向指针解决方案的指针,以解决我为此功能遇到的类似问题

    BOOL OpenBitmap2 ( LPCTSTR pszFileName, char** pszBMPFile)  

是通过分配一个临时指针来存储地址

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

然后重新分配

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

关于为何使用&#34; * pszBMPFile&#34;的任何评论直接与GlobalAlloc没有工作将不胜感激。  我回答了自己的问题。我忘了携带&#34; *&#34;通过pszBMPFile在其他代码行中。所有贡献者的好教训。非常感谢。

答案 8 :(得分:0)

如其他答案中所述,我们需要一个指向该指针的指针。但为什么?

我们需要通过指针传递值,以便能够修改值。如果要修改{% if item.catagory.name == "Fruits" %} ,则需要在int旁进行传递。

在此问题中,我们要修改的值是指针int*(指针从int*更改为已分配内存的地址),因此我们需要将指针传递给指针{ {1}}。

接下来,NULL中的int**是该参数的副本。当我们为局部变量分配内存时,pInt中的那个是完整的。

foo(int*)

所以我们需要一个指向指针的指针,

main()