C - memset vs free

Posted

技术标签:

【中文标题】C - memset vs free【英文标题】: 【发布时间】:2014-08-03 18:18:34 【问题描述】:

我对调用 memset 时内存中实际发生的情况与调用 free 时发生的情况感到困惑。

例如,我有一个指向 char* 数组的指针 A

char** A = (char**)calloc(5, sizeof(char*));
int i;
for(i=0;i<5;i++)

  //filling
  A[i] = (char*)calloc(30, sizeof(char)); 
  scanf("%s", &A[i]);

现在我想重置它我的 char** 指针和所有元素 它指向完全是空的

memset(A, 0, 5);

free(A);

有什么区别?

我对C有点陌生,所以请通俗地说一下,谢谢

【问题讨论】:

【参考方案1】:

不同的是memset实际上设置了一块内存的值,而free返回内存供操作系统使用。

通过使用物理事物的类比,memset(beer, 0, 6) 应用于六包啤酒会将值“0”应用于数组beer 的所有六个成员,而free(beer) 将相当于给出六包送朋友。

【讨论】:

好答案。我可以补充一点,虽然操作系统以不同的方式实现这一点,但至少可以将操作系统想象为持有一系列指向内存块的指针,并且当您使用 malloc(或类似)时,操作系统会返回一个指向该内存块,并在内部将其标记为“正在使用”,以避免在使用时将同一块分配给其他人。当您调用 free 时,您是在告诉操作系统取消设置该块的“正在使用”标志。处理完数据后无法调用 free 会导致一段时间后内存满 - 内存泄漏 可能将内存返回给操作系统或保留它以更快地满足进一步的内存请求(标准)。在第一种情况下,再次取消引用指针可能会导致访问冲突,而在第二种情况下,则更有可能导致程序状态的静默损坏。 确实,这就是为什么我说出于教育目的以这种方式想象它是件好事。不过一般来说,在免费调用之后,最好假设它立即传递给操作系统..因为你不知道什么时候,假设最坏的情况【参考方案2】:

memset 函数将内存区域设置为请求的值。请注意,您提供的大小是字节数

free 函数释放分配的内存,使其无法再使用。调用free 通常不会以任何方式修改内存。在调用free 后使用内存会导致未定义的行为

【讨论】:

【参考方案3】:

这两种方法都不正确,但有些互补。

memset 会将缓冲区的内容设置为给定值,在您的情况下为 0。这将更改指针的值,这将导致您丢失对已分配缓冲区的引用(在每个 A[i] 中)。

free(A)会释放A指向的缓冲区,但是这个缓冲区包含指针,并且它们所指向的每个缓冲区都不会被释放。

简而言之 - memset 不会释放动态分配的缓冲区,并且 free 不会将其设置为零。

正确的方法是这样的:

for(i=0;i<5;i++)

    // complementary to
    // A[i] = (char*)calloc(30, sizeof(char)); 
    free(A[i]);

// complementary to
// char** A = (char**)calloc(5, sizeof(char*));
free(A);
A = NULL; // so no one gets confused...

【讨论】:

也许添加一个注释,全位零不必是NULL-pointer。【参考方案4】:

free 释放内存,这意味着 A 仍将指向相同的内存位置,这现在是无效的。

memset 会将 A 当前指向的内存设置为您想要的任何内容。

【讨论】:

“A 仍将指向”-> 否。A 和所有其他指向已释放内存的指针在调用 free(A) 时变得不确定。如果它们没有变得不确定,trust-in-soft.com/dangling-pointer-indeterminate 中的程序将不会打印“0x7fffb4e003bf is different from 0x7fffb4e003bf”。【参考方案5】:

memset 改变内存地址的内容。它不会改变内存是否被分配/释放。

free 不会改变内存地址的内容。它释放内存块,使其可供程序回收和重用。因此,任何指向该块的指针都会变得无效,并且尝试访问内存应该会导致 Segfault (“如果你很幸运的话”就像我的教授所说的那样)。

当您知道您将再次访问该地址的数据时,请使用memset。当您知道数据将不再被访问并且程序可能会回收该内存时,请使用 free

【讨论】:

【参考方案6】:

memset() 方法只是用给定的字符替换 x 内存字节,分配的内存由指针 *a 指向;

memset(a, 'a', x);

memset()方法的原型是:

void* memset(void*, unsigned int, int);

memset() 的行为类似于strcpy(),但区别在于memcpy() 按原样复制数据(字节),但strcpy 也复制格式化字符串(因此执行时间比memcpy 多)。

但是,free() 方法只是释放内存空间并使其可以被占用。

【讨论】:

【参考方案7】:

虽然其他答案解释了差异,但让我添加一个示例,当 memset() 和 free() 需要按特定顺序一起使用时:

如果 malloc 的内存区域用于存储任何需要删除以防止其他人窥探的关键/有价值信息(例如管理密码或其他密码等与安全相关的内容),您会希望首先擦除该内存区域中的内容,然后对其调用 free() 以将该区域的控制权交还给操作系统。

因此,就像free()是malloc()的反义词,memset(to zero)-then-free()是calloc()的反义词。

【讨论】:

以上是关于C - memset vs free的主要内容,如果未能解决你的问题,请参考以下文章

C语言memset问题

C语言 memset函数

c语言里有memset()怎么用?需要啥头文件?

在JAVA中有没有象C语言里的memset函数

C语言中,memset函数都可以给啥类型的数组清零?

C中关于Memset的简单问题[重复]