C语言中指向重新分配内存块的多个指针

C语言中指向重新分配内存块的多个指针,c,pointers,memory-management,C,Pointers,Memory Management,假设我有多个指向堆内存块的指针。假设第一个指针是内存的所有者,在整个应用程序中,还有几个额外的指针充当句柄。只要所有者是唯一可用的,我们就不会有内存泄漏,也不会双重释放内存块 /* Here is the owner */ size_t block_size = SOME_BLOCK_SIZE; char *owner = malloc(block_size); /* And a few handles that access the block in different places */

假设我有多个指向堆内存块的指针。假设第一个指针是内存的所有者,在整个应用程序中,还有几个额外的指针充当句柄。只要所有者是唯一可用的,我们就不会有内存泄漏,也不会双重释放内存块

/* Here is the owner */
size_t block_size = SOME_BLOCK_SIZE;
char *owner = malloc(block_size);

/* And a few handles that access the block in different places */
char *handle_1 = owner[10];
char *handle_2 = owner[359];
char *handle_3 = owner[172];
到目前为止还不错。后来我们
realloc
要求业主增加容量

char *tmp = realloc(owner, 2 * SOME_BLOCK_SIZE);
if (!tmp) {
    fprintf(stderr, "Error: could not reallocate array\n");
    exit(-1);
}

if (tmp == owner) {
    printf("We all know what happens here...\n");
    printf("the owner array just increased size\n");
}
else {
    printf("We had to move the owner array to a new memory address\n");
    printf("What happens to the handles?\n");
}
有三种可能的结果:

  • realloc
    因内存不足而失败
  • realloc
    无需移动阵列即可成功扩展阵列
  • realloc
    成功扩展了阵列,但它已移动到新的内存区域
  • 我的问题是,在案例3中,我们前面定义的句柄会发生什么变化?我认为,由于它们只是指针变量,而且
    realloc
    函数不知道它们的存在,所以句柄仍然指向旧的内存地址。很容易想象事情会变糟


    我的直觉正确吗?如果是这样,最好的解决方法是什么(除了永远不调整大小)?恐怕我必须保留一个活动句柄的列表,并在检测到
    所有者
    已移动时更新它们。我对如何实现这一点有一个想法,但我宁愿使用其他人的聪明解决方案,也不愿拙劣地重新发明轮子。

    是的,像ryan和true推荐的那样,您应该使用基本指针(所有者)。在realloc的情况下,可以更新此基指针。您的句柄应作为对此基指针的偏移量进行管理

    int handle1_off = 10;
    int handle2_off = 359;
    ...
    
    如果要访问句柄,必须计算实际指针

    memcpy(owner + handle1_off, some_other_pointer, some_size);
    

    是的,像ryan和true一样,您应该使用一个基指针(所有者)。在realloc的情况下,可以更新此基指针。您的句柄应作为对此基指针的偏移量进行管理

    int handle1_off = 10;
    int handle2_off = 359;
    ...
    
    如果要访问句柄,必须计算实际指针

    memcpy(owner + handle1_off, some_other_pointer, some_size);
    

    是的,其他指针也需要在
    realloc
    之后更新。这里有很多选项–例如,将它们存储为偏移量而不是指针,因此您只需要更新一个基指针。存储偏移量是一个简单而聪明的想法。不幸的是,我需要指针地址,因为在我的应用程序中,指针地址被
    gsl\u matrix\u视图
    (一种允许将数组视为二维矩阵的结构)使用。我认为我需要编写一个钩子来更新我的矩阵视图,当我检测到底层数组已经调整大小时。不要复制所有者的内容,而只传递/分发它的地址。作为一个编写大量多线程应用程序的人,这个总体设计是。。令人担忧。是的,其他指针也需要在
    realloc
    之后更新。这里有很多选项–例如,将它们存储为偏移量而不是指针,因此您只需要更新一个基指针。存储偏移量是一个简单而聪明的想法。不幸的是,我需要指针地址,因为在我的应用程序中,指针地址被
    gsl\u matrix\u视图
    (一种允许将数组视为二维矩阵的结构)使用。我认为我需要编写一个钩子来更新我的矩阵视图,当我检测到底层数组已经调整大小时。不要复制所有者的内容,而只传递/分发它的地址。作为一个编写大量多线程应用程序的人,这个总体设计是。。担心