我需要另一个函数内部的malloc()的帮助。但是我看到的是...正在分配的内存用于我的被调用函数中声明的指针,而不是用于main()内部的指针。

我应该如何传递


我编写了以下代码,并得到如下所示的输出。

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


程序输出:

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


#1 楼

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

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


评论


为什么要在保证有NULL指针的条件代码块中调用free!?!?当从main()调用free(* ptr)时,它将尝试释放ummm的input_image,这个词回避了我...没有动态分配。

–詹姆斯·莫里斯(James Morris)
2010年5月14日22:45



和@James:我做了Mark和Matti的建议,但是这次我main()中的_mize(input_image)和我alloc_pixels(...)函数中的_msize(** ptr)都将大小返回为0如果为_msize(* ptr)(单*),则返回262144。

–HaggarTheHorrible
2010年5月14日23:09



@James Morris,我只是复制了问题中发布的代码,并进行了最少的更改。我不想陷入分心的重点。

– Mark Ransom
2010年5月15日,1:50

@vikramtheone,对不起,我有点着急,没有给出应有的完整答案。我已经对其进行了编辑,使其更加完整。希望您能看到它与原始代码有何不同,以及为什么必须这样。

– Mark Ransom
2010年5月15日在2:01



我在MSVS上尝试了同样的方法,但是没有用。 input_image仍然是“错误指针”。可能是什么原因?

–Zeeshan Mahmood
16年4月7日在9:26

#2 楼


我应该如何将指针传递给
函数,并从调用的
函数内部为
传递的指针分配内存?


问问自己:如果您必须编写一个必须返回int的函数,您将如何操作?

您将直接返回它:

int foo(void)
{
    return 42;
}


或通过添加间接级别(即,使用int*而不是int)通过输出参数返回它:

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


所以当您将返回指针类型(T*),这是同一回事:您可以直接返回指针类型: br />
T* foo(void)
{
    T* p = malloc(...);
    return p;
}


评论


感谢您的解释,我太着急了。

– Mark Ransom
2010年5月15日在1:44

+1,我喜欢除了断言之外的所有内容,但是对于这样一个简单的演示来说,它很好。

– Tim Post♦
2010年5月15日下午6:47

我喜欢这个主张。它是功能合同的一部分,调用方应该系统正确地使用该功能。当然,即使是更细微的代码,也可以使NULL out允许,因为它对应于可选的out参数。但这不是alloc_pixels所需要的;这个问题不需要如此复杂。

–研究员
2010年5月15日下午6:56

在调用函数(本例中为main)中释放(* out)是否安全?

–威廉·埃弗里特(William Everett)
2014年1月9日在16:51

@Pinyaka:调用方在结果指针上调用free()是安全的(否则调用方将如何释放分配的内存?)。但是,调用方可能正在执行T * out = foo();。 (第一种形式)或T * out; foo(&out); (第二种形式)。在这两种情况下,调用者都必须调用free(out),而不是free(* out)。

–詹姆士林
2014年1月9日在17:29

#3 楼

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

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


评论


在空指针上调用free()是安全的,该注释是关于什么的?

–卡尔·诺鲁姆
2010年5月14日在22:37

@卡尔·诺鲁姆:很安全,但毫无意义。 IMO,什么都不做的代码只会导致后来阅读它的人们感到困惑,应该避免。

–马蒂(Matti Virkkunen)
2010年5月14日22:38



@Matti Virkkunen:告诉人们不要对NULL指针进行免费调用是毫无意义的,而且是错误的信息-当人们看到违背您建议的代码时,就会使他们感到困惑。

–詹姆斯·莫里斯(James Morris)
2010年5月14日在22:43



@James Morris:很好,很好...现在喜欢更好的措辞?

–马蒂(Matti Virkkunen)
2010年5月14日在22:49

@Carl:我遇到(不是很好)C库,如果要求释放(NULL),它们会崩溃;所以最好还是避免。 (不,我不记得是哪个。很久以前。)

–研究员
2010年5月14日在22:55

#4 楼

您需要通过引用而不是通过副本传递指针,函数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链接后,一个建议,代码示例与我的答案中的相同。 ..但是...在%usize_t调用中将printf(...)类型的格式说明符更改为main()

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

}


评论


我了解自己在做什么错。但是,有一个问题仍然没有解决。当我进行这些更改并使用_msize(input_image)时;在我的main()中,_msize(...)返回0。同时_msize(* ptr);在另一个函数中,我得到的大小为262144。这里出了什么问题?我没有线索。

–HaggarTheHorrible
2010年5月15日,0:30

@vikramtheone:能否显示_msize(...)的函数原型?修改您的问题以突出显示...

–t0mm13b
2010年5月15日在9:07

没关系,它现在可以正常工作:)这是一个深夜工作,我的头脑变得模糊了,我忘了更改main()了。在main()中调用alloc_memory(...)时,我没有发送input_image的地址。

–HaggarTheHorrible
2010年5月15日10:56



#5 楼

这是没有道理的:

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


alloc_pixels返回signed charERRORNO_ERROR),然后将其与NULL(应该用于指针)进行比较。 br />
如果要更改input_image,则需要将指向它的指针传递给alloc_pixels
alloc_pixels签名如下:

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


您可以这样称呼:

alloc_pixels(&input_image, bmp_image_size);


以及内存分配

*ptr = malloc(size);


#6 楼

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

您可以更改alloc_pixels函数的签名,该签名更简单理解,并且您也不需要其他的“状态”变量。

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;

}


#7 楼


仅当将值设置为其地址时,参数分配才有效。


尝试解决此问题之前,应了解两点: > 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;
}


这样,您可以更改i的值。



malloc:

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


这将起作用。

#8 楼

我可以得到一个指向解决该问题的指针解决方案的唯一方法,该函数只有在分配一个临时指针来存储地址的情况下,才能使用该功能



    BOOL OpenBitmap2 ( LPCTSTR pszFileName, char** pszBMPFile)  


然后重新分配

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


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

评论


抱歉,格式化。只是不确定如何去做。

– PeterS
17年11月25日在23:07

#9 楼

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

我们需要通过指针传递值,以便能够修改值。如果要修改int,则需要将其传递给int*。在这个问题中,我们要修改的值是指针int*(指针从NULL更改为分配的地址)内存),因此我们需要将指针传递给指针int**。通过执行以下操作,pInt内部的foo(int*)是该参数的副本。当我们将内存分配给局部变量时,main()中的一个完好无损。

void foo(int* pInt)
{
   pInt = malloc(...);
}
int main()
{
   int* pInt;
   foo(pInt);
   return 0;
}


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

void foo(int** pInt)
{
   *pInt = malloc(...);
}
int main()
{
   int* pInt;
   foo(&pInt);
   return 0;
}