当指针具有偏移量时,realloc会崩溃

4

我有一个简化的C程序来演示问题。当我尝试使用指针调用 realloc 时,它可以正常工作,但是如果我尝试向指针添加偏移量(即从数组中的后续元素开始),它将失败。

# include <stdio.h>
# include <stdlib.h>

struct arbNum{
    unsigned char* bytes;
    long len;
};

void trim(struct arbNum* num){
    printf("%d,%d,%d,%d\n",num->bytes,num->bytes[0],num->bytes[1],num->len);
    unsigned char* nbytes = realloc(num->bytes,num->len);
    printf("Realloc successful.\n");
    num->bytes = nbytes;
}

int main(void){
    struct arbNum p = {calloc(2,1),2};
    trim(&p);
}

作为示例,这将输出:
9247152,0,0,2
Realloc successful.

但是,从上面的代码中,将 realloc(num->bytes,num->len); 改为 realloc(num->bytes+1,num->len-1); 会改变输出/行为如下:

10361264,0,0,2

然后程序崩溃了。也许我完全不理解指针,但我目前的理解是它们本质上是存储另一个值的地址。在这种情况下,为什么提供pointer+1不会指向指针高一位存储的地址中的值,或者换句话说,作为由该指针指向的数组的第一个元素的内容。我正在尝试的是将从第一个元素开始指向num.bytes的数组复制到内存中的新地址,但显然,由于某种原因,它失败了。
1个回答

9
不,你只能在先前由malloc()或类似函数返回的实际指针上使用realloc()。否则,这将导致未定义行为。引用C11,第7.22.3.5节:“如果ptr是空指针,则对于指定大小,realloc函数的行为类似于malloc函数。否则,如果ptr与先前由内存管理函数返回的指针不匹配,或者如果该空间已被调用freerealloc函数释放,则行为未定义。[....]”因此,您不能使用指针算术生成新地址,将其传递给realloc()并期望部分重新分配,这毫无意义。

好的。显然我可以使用memcpy来做我想要的事情。 - user2649681
@user2649681 嗯,甚至在那之前,你就会遇到未定义行为(UB)。 - Sourav Ghosh
@user2649681 "显然我可以使用memcpy来做我想要的事情" --> 可能不太靠谱。但是memmove()可能会起作用。 - chux - Reinstate Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接