关于rvalues'范围和内存泄漏

时间:2016-04-10 09:35:55

标签: c++ c memory-management rvalue

如果你停留在同一个街区,那么rvalues会发生什么?"永远"?

假设我有以下代码:

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

在每次迭代中,右值char *将从ctime返回,但它会在迭代结束时处理还是仅在块完成后才会被处理?

如果它仅在块完成时,那么经过几百万次迭代后,内存可以用完成的右值char*填充吗?

(我使用cc++对此进行了标记,因为我还想知道这两者之间是否存在差异。

3 个答案:

答案 0 :(得分:2)

由于历史原因,C库中的函数返回不同类型的内存:

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

您只需需要知道您正在使用的特定库调用将返回哪个类,以便了解您是否需要free()该内存。请参阅相应呼叫的手册页。

ctime()的情况下,循环迭代绝对无关紧要。由于库在每次迭代时返回相同的缓冲区地址,它被写入堆栈框架中的非常相同的位置,因此不存在内存泄漏。如果您在循环中调用strdup(),则会产生内存泄漏。

答案 1 :(得分:1)

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

本地变量,例如

char buff[999];
time_t timer;

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

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

当函数退出时,通过销毁堆栈帧自动处理所有局部变量。同样,这只需通过再次移回堆栈指针即可完成。这与静态函数变量(只是具有有限可达性的全局变量)和动态分配(堆)变量形成对比,这些变量必须明确分配或免费提供。

堆栈帧有点过于复杂,无法完全覆盖,但我建议您阅读它们,因为理解函数调用的工作原理确实有助于对C编程的一般理解。

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

答案 2 :(得分:1)

{C}和C ++中ctime返回的指针称为。它不是对象,因此它没有生命周期或存储持续时间。

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

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

在C中,函数的返回值可以被访问直到当前语句的结尾(即你的情况下的下一个;),尽管对于标量类型,这是不相关的,因为没有表达此类访问权限的语法。此条款引用类似printf("%d\n", foo().x);的内容,其中foo()按值返回结构。

代码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个返回值对象,但它们都在;处死亡。

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