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


69

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

我正在从我的函数传递一个指针和一个大小给函数main(),我想malloc()从被调用的函数内部使用该指针动态分配内存,但是我看到的是...正在分配的内存是用于在我的调用函数中声明的指针,而不用于main()

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


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

资源:

程序输出:

Answers:


80

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


5
<S>为什么要在保证有NULL指针的条件代码块中进行免费调用!?!?</ S>free(*ptr)main()try to free调用时的意愿input_image是ummm,该术语回避了我...不是动态的已分配。
詹姆斯·莫里斯

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

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

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

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

100

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

问问自己:是否必须编写必须返回一个 int您将如何做?

您可以直接将其返回:

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

因此,当您返回指针类型(T*)时,它是同一回事:您可以直接返回指针类型:

或添加一个间接级别:


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

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

1
我喜欢这个主张。它是功能合同的一部分,调用方应该系统正确地使用该功能。当然,即使更微妙的代码out都与可选的输出参数相对应,也可能允许NULL 。但这不是必需的alloc_pixels。这个问题不需要如此复杂。
多纳研究员2010年

1
在调用函数(本例中为main)中释放(* out)是否安全?
威廉·埃弗里特2014年

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

8

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


1
调用free()null指针是安全的,该注释是关于什么的?
卡尔·诺鲁姆

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

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

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

@Carl:我遇到过(不是很好)C库,如果被要求崩溃,free(NULL);那么无论如何都要避免。(不,我不记得是哪个。很久以前。)
Donal Fellows 2010年

4

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

主要()
{
   无符号字符* input_image;
   无符号整数bmp_image_size = 262144;

   if(alloc_pixels(&input_image,bmp_image_size)== NULL)
     printf(“ \ nPoint2:分配的内存:%d个字节”,_msize(input_image));
   其他
     printf(“ \ nPoint3:未分配内存”);     

}

有符号字符alloc_pixels(无符号字符** ptr,无符号整数大小)
{
    签名字符状态= NO_ERROR;
    * ptr = NULL;

    * ptr =(无符号字符*)malloc(size);

    如果((* ptr)== NULL)
    {
        状态=错误;
        / *免费(ptr);
        printf(“ \ nERROR:内存分配未成功完成!”); * /
    }

    printf(“ \ nPoint1:分配的内存:%d个字节”,_msize(* ptr));

    返回状态;
}

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

编辑:在查看了OP提供的msdn链接后,提出了一个建议,该代码示例与我的答案中的早期示例相同....但是...在中的调用中,将格式说明符更改%u为该size_t类型。printf(...)main()

主要()
{
   无符号字符* input_image;
   无符号整数bmp_image_size = 262144;

   if(alloc_pixels(&input_image,bmp_image_size)== NULL)
     printf(“ \ nPoint2:分配的内存:%u个字节”,_msize(input_image));
   其他
     printf(“ \ nPoint3:未分配内存”);     

}

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

@vikramtheone:能否显示_msize(...)的函数原型?修改您的问题以强调以下内容:
t0mm13b 2010年

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

2

这根本不符合逻辑 :

alloc_pixels返回一个signed charERRORNO_ERROR),然后将其与NULL(应该用于指针)进行比较。

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

您可以这样称呼它:

和内存分配


1

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

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

您可以在main中调用上述函数:


1

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

在尝试解决此问题之前,应了解两点:
1. C函数:传递给该函数的所有参数将是该函数中的一个副本。

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

因此,如果要在函数中更改i,则需要了解事物及其副本之间的区别:

副本与事物共享,而不与地址共享。

那是他们唯一的区别。

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

例如,有一个新函数fun_addr:

这样,您可以更改我的价值。

  1. malloc

fun_addr函数的关键点是,您已经向该函数传递了一个地址。您可以更改该地址中存储的值。

malloc会做什么?

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

请看以下说明:

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

看到?这是相同的问题,将值永久分配给传递给函数的参数。此时,值为address

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

因此,代码应为:

这将工作。


1

我可以得到指向解决该问题的指针解决方案的唯一方法

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

然后重新分配

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


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

0

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

我们需要通过指针传递值,以便能够修改值。如果要修改int,则需要在旁边传递它int*

在这个问题中,我们要修改的值是一个指针int*(从NULL为分配的内存的地址),因此我们需要将指针传递给该指针int**

通过执行以下操作,pInt内部foo(int*)是参数的副本。当我们为局部变量分配内存时,中的一个main()是完整的。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.