提问人:HaggarTheHorrible 提问时间:5/15/2010 最后编辑:Jonathan LefflerHaggarTheHorrible 更新时间:6/2/2020 访问量:116919
C 编程:另一个函数中的 malloc()
C Programming: malloc() inside another function
问:
我需要有关另一个函数的帮助。malloc()
我正在从我的函数传递指针和大小,我想使用调用的函数内部动态地为该指针分配内存,但我看到的是......正在分配的内存是为我调用的函数中声明的指针,而不是为 .main()
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;
}
程序输出:
Point1: Memory allocated ptr: 262144 bytes
Point2: Memory allocated input_image: 0 bytes
答:
您需要将指向指针的指针作为函数的参数传递。
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;
}
评论
free(*ptr)
main()
input_image
如果希望函数修改指针本身,则需要将其作为指针的指针传递。下面是一个简化的示例:
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()
free(NULL);
这没有意义:
if(alloc_pixels(input_image, bmp_image_size)==NULL)
alloc_pixels
返回一个 ( 或 ),然后将其与(应该用于指针)进行比较。signed char
ERROR
NO_ERROR
NULL
如果要更改,则需要将指向它的指针传递给 。 签名如下: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);
我应该如何传递指向 函数并为 从被调用的内部传递指针 功能?
问问自己:如果你必须编写一个必须返回 的函数,你会怎么做?int
你可以直接返回它:
int foo(void)
{
return 42;
}
或者通过添加间接级别(即,使用 而不是 ):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(...);
}
评论
out
alloc_pixels
free()
T* out = foo();
T* out; foo(&out);
free(out)
free(*out)
你需要通过引用而不是复制来传递指针,函数中的参数需要 & 号和 & 来传回指针的地址 - 即在 C 语言中通过引用调用。alloc_pixels
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
free
编辑:在查看了 OP 提供的 msdn 链接后,建议,代码示例与我的回答中的前面相同......但。。。在 中的调用中将格式说明符更改为类型。%u
size_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"); }
评论
在您的初始代码中,当您将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;
}
仅当您将值设置为其地址时,参数的赋值才有效。
在尝试解决此问题之前,您应该了解 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;
}
通过这种方式,您可以更改 i 的值。
- 马洛克:
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);
}
这个会起作用的。
我唯一可以获取指向指针解决方案的指针解决方案的方法,以解决我在这个函数中遇到的类似问题
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
关于为什么直接在 GlobalAlloc 中使用“* pszBMPFile”不起作用的任何评论将不胜感激。 我回答了自己的问题。我忘了在其他代码行中用 pszBMPFile 携带“*”。所有贡献者的教训都很好。非常感谢。
正如其他答案中提到的,我们需要一个指向指针的指针。但是为什么?
我们需要通过指针传递值才能修改值。如果要修改 ,则需要通过 .int
int*
在这个问题中,我们要修改的值是一个指针(指针从更改为分配的内存的地址),因此我们需要传递指针到指针。int*
NULL
int**
通过执行 followed,里面是参数的副本。当我们将内存分配给局部变量时,其中的内存是完整的。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;
}
评论