C - 通过释放指向此内存的指针posix_memalign释放分配的内存


使用posix_memalign

分配内存时,在指向已分配内存指针的指针上调用free是否会释放所有已分配的内存? 在此示例中,当我freepointer_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 ffff ff ff ff ff ff

ff ff ff ff ff ff ff ff ff

使用posix_memalign分配内存时,调用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的调用中。

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_data不指向与data相同的地址,特别是不是posix_memalign返回的地址,这是您可以合法free()的唯一地址。 但是free(*actually_a_pointer_to_data)等同于free(data)

最新更新