关于右值的范围和内存泄漏

About rvalues' scope and memory leaks

如果你留在同一个块中,右值会发生什么变化"forever"?

假设我有以下代码:

char buff[999];
time_t timer;
while(true){
...
    time(&timer);
    strcpy(buff, ctime(&timer));
...
}

在每次迭代中,右值 char * 将从 ctime 中 return,但它会在迭代结束时被释放,还是仅在块完成时被释放?

如果只是在块完成时,那么在几百万次迭代之后,内存可以用完成的右值填充char*对吗?

(我用 cc++ 标记了这个,因为我也想知道这两者之间是否有区别)

由于历史原因,C 库中的函数 return 不同 class 内存:

  • 不需要释放的静态分配内存。该库通常在其代码中将其声明为静态数组,并将在每次函数调用时重新使用相同的内存区域。 ctimelocaltime 就是这方面的例子。 不要 释放此内存。 (可能值得一提的是,这些函数被认为已被弃用,并且由于它们不适合多线程操作而逐渐消失)
  • 调用者需要 释放的动态分配内存。该内存由库函数动态分配,该库函数使用 malloc() 分配该内存,将指针返回给您,并希望您在完成后 free() 该内存。 strdup() 将是这种形式的一个很好的例子。

您只需需要知道您正在使用的特定库调用class是什么return,以便了解您是否需要free()那个记忆与否。请查阅相应调用的手册页。

ctime() 的情况下,循环中的迭代绝对无关紧要。由于库 returns 每次迭代的缓冲区地址,它被写入堆栈帧中的相同位置没有内存泄漏这样的事情。如果您在循环中调用 strdup(),则会造成内存泄漏。

(我在这里谈论的是 C,对于 C++,这要复杂得多)

局部变量比如你的

char buff[999];
time_t timer;

...通常在输入函数时一起分配。这些变量要么在堆栈帧中分配 space(在 buff 的情况下),要么直接在硬件寄存器上分配(在定时器的情况下可能)。

所有这些分配都是在一条机器指令中一起完成的,只需将指针移动到栈顶即可。每个函数调用的每个局部变量只有一个实例,因此 没有内存填满的危险,因为您在循环中使用它们。此外,对于内存区域可以增长的大小(大约 10 兆字节),全球限制相对较低。

所有局部变量在函数退出时通过销毁栈帧自动释放。同样,这只需再次将堆栈指针移回即可完成。这与静态函数变量(它们只是具有有限可达性的全局变量)和必须显式分配或释放的动态分配(堆)变量形成对比。

堆栈帧有点太复杂,无法在此处完整介绍,但我建议您仔细阅读它们,因为了解函数调用的工作原理确实有助于全面了解 C 编程。

如果您对变量存储有任何更具体的问题,我相信您可以在这里找到有关堆栈溢出的帮助,因为我们大多数 C 程序员都喜欢谈论这类事情:)

ctime 编辑的指针 return 在 C 和 C++ 中都称为 value。它不是一个对象,因此它没有生命周期或存储持续时间。

你的问题就像在问:在代码for(;;) { 10 + 10; }中,内存会被20填满吗? (答案是:否)。

(不要与 C++ 中的 temporaries 混淆,它们是对象并且有生命周期)。

在 C 中,可以访问函数的 return 值直到当前语句结束(即在您的情况下为下一个 ;),尽管对于标量类型来说这是不相关,因为没有语法可以表达这种访问。此条款指的是类似 printf("%d\n", foo().x); 的内容,其中 foo() return 是一个值结构。

代码 printf("%d %d %d %d %d %d %d %d %d %d\n, foo().x, foo().x, foo().x, foo().x, foo().x, foo().x, foo().x, foo().x, foo().x, foo().x); 确实需要编译器实现 10 个 return 值对象,但它们都死于 ;

注意。你的问题包含一个固有的误解。当达到 } 时,块结束,即使还有另一次迭代。下一次迭代是一个新块,块内声明的变量在概念上被销毁并在每次迭代时重新创建。