在这个问题中,我指的是另一个堆栈溢出问题,因为我没有足够的点来评论它。
请参阅:Valgrind Reports Invalid Realloc
**简而言之:**为什么指令buffer = trim(buffer);
必须写在函数外部?为什么不能写在函数内部,如phrase = (char*)realloc(phrase, strlen(phrase)+1);
?
**深度:**假设我传递任何指向函数的指针--比如const *str;
--那么通过执行str++;
,我可以创建一个副作用,并改变字符串的起始位置。
但是,为什么不能通过动态内存管理函数(如malloc
和realloc
)为函数重新分配另一个值呢?
为什么不能直接设置str = (char*) realloc(str, strlen(str) + 1 * sizeof(char));
?
这个副作用和另一个副作用有什么不同呢?难道我不能假设把str
移动到我想移动的地方吗?
1条答案
按热度按时间lf5gs5x21#
C通过传值传递所有参数。看一下被调用函数的参数,就像这个函数的局部变量,由调用者给出的参数的副本初始化。
如果我们传递一个指针,我们可以“模拟”通过引用传递。通过解引用指针,我们可以访问位于被调用函数之外的“被引用”对象。但是这个指针仍然是通过值传递的,这意味着它是参数的副本,初始化参数。
所以你可以对参数中的指针做任何你想做的事情,覆盖它,增加或减少它,甚至
NULL
它。这对调用者中指针的来源没有影响。你的问题环节的问题可以归结为:
这里我们需要区分
realloc()
的多种情况。realloc()
返回NULL
,因为没有足够的内存来满足请求。以前的地址仍然有效。realloc()
返回相同的地址,因为这样可以满足请求,由于返回的地址与前一个地址相等,所以都有效。realloc()
返回一个新地址。以前的地址现在无效。其中,第三种情况是常见的,它导致了记录的问题。
因为
caller()
中的buffer
没有被called()
改变,仅仅是因为called()
不能访问它,它仍然保存着以前的地址。现在当用这个无效地址调用free()
时,错误被检测到。要更正此错误,
caller()
需要使用返回值。执行此操作的正确方法是:另一种方法是将 pointer to
buffer
传递给called()
,让它正确地修改buffer
。但是这种类型的重定向通常会生成可读性较差的代码。然而,为了方便函数,您可能会决定采用这种方法。