为什么在缺少width参数时fprintf导致内存泄漏并无法正常运行

mor*_*ten 3 c c++ printf memory-leaks

以下简单程序的行为异常。有时它打印“ 0.00000”,有时它打印的“ 0”超出我的计算。有时,它会耗尽系统上的所有内存,然后系统要么终止某些进程,要么由于bad_alloc失败。

#include "stdio.h"

int main() {
  fprintf(stdout, "%.*f", 0.0);
}
Run Code Online (Sandbox Code Playgroud)

我知道这是fprintf的不正确用法。应该有另一个参数指定格式的宽度。令人惊讶的是,这种行为是不可预测的。有时似乎使用默认宽度,而有时却非常严重。难道这不能总是失败或总是使用某些默认行为吗?

我在工作中的一些代码中遇到了类似的用法,并花了很多时间弄清楚发生了什么。它似乎仅在调试版本中发生,而在使用gdb进行调试时则不会发生。另一个好奇之处是,通过valgrind运行它会始终导致打印很多“ 0”的情况,否则这种情况很少发生,但是也不会发生内存使用问题。

我正在运行Red Hat Enterprise Linux 7,并使用gcc 4.8.5进行了编译。

mel*_*ene 5

Formally this is undefined behavior.

As for what you're observing in practice:
My guess is that fprintf ends up using an uninitialized integer as the number of decimal places to output. That's because it'll try to read a number from a location where the caller didn't write any particular value, so you'll just get whatever bits happen to be stored there. If that happens to be a huge number, fprintf will try to allocate a lot of memory to store the result string internally. That would explain the "running out of memory" part.

If the uninitialized value isn't quite that big, the allocation will succeed and you'll end up with a lot of zeroes.

And finally, if the random integer value happens to be just 5, you'll get 0.00000.

Valgrind可能会始终如一地初始化程序看到的内存,因此行为变得确定。

难道这不能总是失败吗

如果您使用,我很确定它甚至不会编译gcc -pedantic -Wall -Wextra -Werror