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;
}
#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链接后,一个建议,代码示例与我的答案中的相同。 ..但是...在
%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"); }
评论
我了解自己在做什么错。但是,有一个问题仍然没有解决。当我进行这些更改并使用_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 char
(ERROR
或NO_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;
}
评论
为什么要在保证有NULL指针的条件代码块中调用free!?!? S>当从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