提问人:alex 提问时间:2/16/2021 最后编辑:anastaciualex 更新时间:2/16/2021 访问量:150
malloc 如何在包装函数中工作?[复制]
How does malloc work within wrapper function? [duplicate]
问:
我有一个问题专门针对:
void* malloc (size_t size);
在互联网上数百万个网站上可以找到的常规示例中,它表明正确的使用方式如下:malloc
int main()
{
int* num;
num = malloc(sizeof(int));
*num = 10;
printf("Value = %d\n", *num);
free(num);
return 0;
}
但是,如果我想在函数中分配内存并在 main 中使用它,如下所示,那么唯一的选择是以下方式实现该函数:
void func_alloc(int** elem, int num_value)
{
*elem = malloc(sizeof(int));
**elem = num_value;
}
int main()
{
int* num;
func_alloc(&num, 10);
free(num);
return 0;
}
我错误地认为,下面的代码会起作用:
void func_alloc(int* elem, int num_value)
{
elem = malloc(sizeof(int));
*elem = num_value;
}
int main()
{
int* num;
func_alloc(num, 10);
free(num);
return 0;
}
您能否解释一下,或者提供一个资源链接,并解释为什么它只能以这种方式工作?
我真的不明白为什么我需要双指针作为输入参数,为什么在另一种情况下会出现“分段错误”......
提前致谢;)
答:
如果您有:
#include <stdio.h>
void foo(int x)
{
x = 9;
}
int main(void)
{
int a = 1;
foo(a);
printf("%d\n", a);
}
您可能不希望 in 的值仅仅因为分配给 而改变,对吧?它不会更改,因为参数是按值分配的。中的变量 , 和 in 是两个不同的变量。a
main()
foo()
x
x
foo()
a
main()
这同样适用于您的代码。 in 是与 in 不同的变量,赋值给前者不会改变后者的值。事实上,这两者是类型的,而不是 ,这与此没有区别。elem
func_alloc()
num
main()
int *
int
也就是说,您也可以返回从中获取的指针,例如malloc()
int *alloc_int(int value)
{
int *p = malloc(sizeof(int));
*p = value;
return p;
}
(并不是说这似乎很有意义。int
我错误地认为,下面的代码会起作用。
在 C 中,参数是按值传递的,当你将指针作为函数的参数传递时,你传递的是指针的值,基本上是它的副本,而不是指针本身,会改变该指针的值,但由于你传递的是副本,所以这就是更改的内容,而不是原始指针, 那个保持不变。malloc
在第二个代码片段中,工作代码,大致意味着使此指针指向通过(假设它成功)提供给我的这个有效内存地址,指向您作为参数传递的指针的指针的值保持不变,它是一个副本并不重要,因为它没有更改,它仍然是作为参数传递的相同地址, 指针的地址,该指针现在指向 给出的内存位置。*elem = malloc(sizeof(int));
elem
malloc
elem
num
malloc
**elem = num_value
表示存储在指针中存储的地址 哪里是指向的,这是哪里指向的地方,这是先前由 给出的新内存块。num_value
elem
num
malloc
话虽如此,这不是唯一的选择,您可以使用本地指针,返回它并将其分配给调用方的另一个本地指针,这仍然是一个副本,但它是已更改指针的副本:
int *func_alloc(int num_value)
{
int *elem = malloc(sizeof *elem); //more idiomatic
if(elem == NULL){ // check for allocation errors
perror("malloc" );
exit(EXIT_FAILURE);
}
*elem = num_value;
return elem;
}
int main()
{
int* num = func_alloc(10);
free(num);
return EXIT_SUCCESS;
}
脚注:
在第三个代码片段中,鉴于它未初始化,释放是一个坏主意,我想你知道很多,但我想我会提到它。这可能是您遇到段错误的原因,无论垃圾值如何,都将假定为有效的内存地址,并尝试解除分配它,这样做将调用未定义的行为。如果它是 NULL,那就另当别论了,它是定义良好的行为(除了在一些非常古老的标准中)。在大多数情况下,在声明变量时初始化变量是一个好主意。num
num
free
评论解释:
void func_alloc(int* elem, int num_value)
{
/* elem points to address gave by malloc, let's say 0x12345678 */
elem = malloc(sizeof(int));
/* at address 0x12345678 you have now your num_value */
*elem = num_value;
/* end of the function. Changes made to parameters passed by value are lost */
}
int main()
{
int* num;
/* num is a pointer to an address you could not have write access to, you actually don't know */
func_alloc(num, 10);
/* As C arguments are passed by value, changes made into the function are lost */
/* You try to free num which is still a pointer to an address you potentially have no access to => SEGFAULT */
free(num);
return 0;
}
编辑: 此示例中未显示,但最好始终检查 malloc 返回的指针是否为 NULL,否则应退出而不尝试为指针赋值。
评论
elem
num
main
free(num)