【问题标题】:free allocated memory by posix_memalign by freeing a pointer that points to this memoryposix_memalign 通过释放指向该内存的指针来释放分配的内存
【发布时间】:2020-11-21 11:26:29
【问题描述】:

当使用posix_memalign 分配内存时,在指向已分配内存指针的指针上调用free 是否会释放所有已分配的内存? 在这个例子中,当我 free pointer_to_data 然后查看原始指针时,我仍然在所有分配中看到相同的数据,但不是最后一个!

unsigned char *data = nullptr;
unsigned int  data_size = 512;

posix_memalign((void **) &data, 16, data_size);
memset(data, 0, data_size);

for (int i = 0; i < data_size; i++){
    data[i] = 0xff;
}

unsigned char *pointer_to_data = data;
free(pointer_to_data);


for (int i = 0; i < data_size; i++){
    printf( " %x ",data[i]);
}

ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 10 0

【问题讨论】:

    标签: c pointers malloc


    【解决方案1】:

    当使用posix_memalign 分配内存时,会调用free on 指向已分配内存指针的指针 free 所有分配的内存?

    目前尚不清楚“指向已分配内存指针的指针”是否掩盖了误解,或者只是措辞不佳。我没有看到与所提供示例相匹配的解释方式。

    要释放分配的内存,包括通过posix_memalign 分配的内存,必须向free() 传递一个指向分配函数提供的基地址的指针。 posix_memalign() 在标准分配函数中是不寻常的,因为它通过 out 参数写入该指针而不是返回它,所以在这里 ...

    unsigned char *data = nullptr;
    unsigned int  data_size = 512;
    
    posix_memalign((void **) &data, 16, data_size);
    

    ...有问题的基地址记录在变量data 中,其自己的地址作为第一个参数传递给posix_memalign 以使该函数能够修改其值。 posix_memalign 写入的指针值随后必须传递给 free,但所有 C 函数参数都是按值传递的,因此只有传递的值才能产生影响,而不是产生该值的表达式。

    因此,如果你这样做......

    unsigned char *pointer_to_data = data;
    

    ...那么您刚刚将data 的(指针)值复制到变量pointer_to_data,因此data == pointer_to_data 是真的。然后,您可以通过将从任一变量获得的(相同)值传递给free() 来释放分配的块。这是释放分配空间的有效方法:

    free(pointer_to_data);
    

    你接着说

    在这个例子中,当我释放pointer_to_data然后查看 原始指针我仍然在所有分配中看到相同的数据,但不是 最后一个!

    释放分配的空间使其可用于重新分配,并终止分配对象的生命周期。尝试访问生命周期已结束的对象的值会产生未定义的行为。如果您(不安全地)假设您可以继续使用指向已释放空间的指针来检查不再分配的内存,那么没有理由期望内存已经改变,但也没有理由期望它没有.

    特别是,内存分配器通常不会特意覆盖已释放内存块的内容,但在某些情况下,它可能用于修改部分或全部内存,或者部分或全部可能在它可用后不久被重新分配并可能被覆盖,例如在您的示例代码中对 printf 的调用中。

    【讨论】:

      【解决方案2】:
      unsigned char *pointer_to_data = data;
      

      这不是指向指针的指针,它是指针的副本,也称为别名。它指向与data 本身相同的地址。调用free(pointer_to_data) 与调用free(data) 的效果完全相同。

      释放一块内存并不能保证它之前的内容不可访问。相反,尝试访问该内存区域是未定义的行为。如果分配器选择保留该内存区域以供将来分配,您可能会看到以前存在的数据。您可能会看到分配器本身放置在那里的元数据。如果空间已被再次分配,您可能会看到由程序的不同部分放置在那里的数据。如果内存已返回给操作系统并且未映射,您可能会遇到分段错误。从字面上看,任何事情都可能合法地发生,而且大多数可能性都是你不喜欢的。因此,您有责任确保您的程序不会那样做,并且不会像您所写的那样编写代码。

      重复一遍,datapointer_to_data 之间的区别与此无关。如果您改为使用free(data),您会看到完全相同(未定义)的行为。

      (如果存储在该块中的数据是敏感的,例如加密密钥,那么您需要确保在 free() 它之前 覆盖它;您不能依赖 free()为你做这件事。这是一件比看起来更难的事情,因为数据的其他副本可能存在于其他地方,你必须确保将它们全部覆盖。如果这是你的情况,你可能应该得到专家建议。)

      请注意,上面提到的所有内容对于malloc()posix_memalign() 都是一样的。

      如果你真的想要一个指向指针的指针,你会写

      unsigned char **actually_a_pointer_to_data;
      actually_a_pointer_to_data = &data;
      

      在这种情况下,free(actually_a_pointer_to_data) 本身就是未定义的行为,因为actually_a_pointer_to_datadata 指向的地址不同,尤其不是posix_memalign 返回的地址,这是唯一的你可以合法地free()。但是free(*actually_a_pointer_to_data) 将等同于free(data)

      【讨论】:

        猜你喜欢
        • 2011-11-15
        • 1970-01-01
        • 2014-09-05
        • 1970-01-01
        • 2020-06-23
        • 1970-01-01
        • 2012-12-28
        • 2016-07-18
        • 1970-01-01
        相关资源
        最近更新 更多