[英]C Programming: malloc() inside another function
我需要另一个 function中的malloc()
帮助。
I'm passing a pointer and size to the function from my main()
and I would like to allocate memory for that pointer dynamically using malloc()
from inside that called function, but what I see is that.... the memory,正在分配的指针是在我称为 function 中声明的指针,而不是在main()
中的指针。
我应该如何将指针传递给 function 并从被调用的 function 内部为传递的指针分配 memory ?
我编写了以下代码,得到了如下所示的 output。
资源:
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
的函数,你会怎么做?
您可以直接返回它:
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(...);
}
您需要将指向指针的指针作为参数传递给函数。
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;
}
如果您希望您的函数修改指针本身,则需要将其作为指向指针的指针传递。 这是一个简化的示例:
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
中的参数需要 & 来传递指针的地址 - 在 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; }
我已经注释掉了alloc_pixels
函数中的两行free(ptr)
和 "ERROR: ...",因为这很令人困惑。 如果内存分配失败,您不需要free
指针。
编辑:在查看了size_t
提供的msdn链接后,一个建议,代码示例与我之前的回答中的相同......但是......在%u
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"); }
正如其他答案中提到的,我们需要一个指向指针的指针。 但为什么?
我们需要通过指针传递值才能修改值。 如果要修改int
,则需要通过int*
传递它。
在本题中,我们要修改的值是一个指针int*
(指针从NULL
变成了分配内存的地址),所以我们需要传递一个指向指针int**
的指针。
通过遵循, foo(int*)
中的pInt
是参数的副本。 当我们为局部变量分配内存时, 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;
}
这根本不符合逻辑 :
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);
仅当您将值设置为其地址时,参数的分配才会起作用。
在尝试解决此问题之前,您应该了解两点:
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 将分配一个新的内存空间,并返回指向该地址的指针 back 。
看看这个指令:
int *array = (int*) malloc(sizeof(int) * SIZE);
你正在做的是让数组的值等于malloc返回的地址。
看? 这是同一个问题,将值永久分配给传递给函数的参数。 此时,值为address
。
现在,将地址(由 malloc 返回)分配给地址(存储旧地址)。
所以代码应该是:
void fun_addr_addr(int **p) {
*p = (int*) malloc(sizeof(int) * SIZE);
}
这个会起作用的。
在您的初始代码中,当您将 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;
}
我可以获得指向指针解决方案的唯一方法,以解决我在此函数中遇到的类似问题
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
任何关于为什么直接将“* pszBMPFile”与 GlobalAlloc 一起使用不起作用的评论将不胜感激。 我回答了我自己的问题。 我忘记在其他代码行中使用 pszBMPFile 携带“*”。 所有贡献者的好教训。 非常感谢。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.