为什么我可以重新定位一个指针作为一个函数的参数,但不重新分配一个新的值后,它' realloc ' ?



在这个问题中,我指的是另一个stackoverflow问题,因为我没有足够的分数来评论它。


参见:Valgrind Reports Invalid Realloc

简而言之:为什么指令buffer = trim(buffer);必须写在函数之外?为什么不能在函数内部写成phrase = (char*)realloc(phrase, strlen(phrase)+1);呢?


深度:假设我将任何指针传递给一个函数-例如const *str;-然后通过执行str++;,我可以创建一个副作用并改变字符串的起始位置。

但是为什么我不能通过动态内存管理函数(如mallocrealloc)为函数重新分配另一个值呢?

为什么不能直接设置str = (char*) realloc(str, strlen(str) + 1 * sizeof(char));?

是什么使这种副作用与另一种不同?假设我不能把str移动到我想去的地方吗?

C passall按值的参数。查看被调用函数的形参,就像该函数的局部变量一样,由调用者给出的实参的副本初始化。

我们可以"仿真"如果传递指针,则按引用传递。通过对指针解引用,可以访问"被引用"的对象。位于被调用函数之外的对象。但是这个指针仍然是按值传递的,这意味着它是实参的副本,初始化了形参。

注意:c++和其他语言的引用实际上就是指针。不过,还有一些额外的语义。您可能需要查看生成的机器码。

所以你可以对参数中的指针做任何你想做的事情,覆盖它,自增或自减,甚至NULL它。这对调用方指针的来源没有影响。

你所链接的问题的问题可以归结为:

char* called(char* pointer)
{
return realloc(pointer, /* some irrelevant value */);
}
void caller(void)
{
char* buffer = malloc(/* some irrelevant value */);
/* ignore returned pointer */ called(buffer);
free(buffer); /* here Valgrind reports an error */
}

我们需要在这里区分realloc()的多种情况。

  1. realloc()返回NULL,因为没有足够的内存满足请求。原地址仍然有效。
  2. realloc()返回相同的地址,因为这样可以满足请求。由于返回地址和前地址相等,因此两者都有效。
  3. realloc()返回新地址。原来的地址现在无效。

其中,第三种情况是最常见的,它导致了文档中的问题。

因为caller()中的buffer没有被called()改变,仅仅是因为called()无法访问它,所以它仍然保留前一个地址。现在,当使用这个无效地址调用free()时,会检测到错误。

要纠正这个错误,caller()需要使用返回值。正确的方法TM是:

void caller(void)
{
char* buffer = malloc(/* some irrelevant value */);
char* new_buffer = called(buffer);
if (new_buffer != NULL) {
buffer = new_buffer;
} else {
/* handle the re-allocation error, the address in buffer is still valid */
}
free(buffer);
}

另一种方法是将指向buffer指针传递给called(),并让它正确地修改buffer。但是这种类型的重定向通常会生成可读性较差的代码。但是,为了方便起见,您可能会决定走这条路。

相关内容

  • 没有找到相关文章

最新更新