我希望有一个最简的o-damn-malloc-just-failed处理程序,它可以将一些信息写入文件(可能只是标准错误)。 我更喜欢使用fprintf()而不是write(),但如果fprintf()本身尝试进行内存分配,则这将失败。
是否存在某种保证,无论是在C标准中还是仅在glibc中,fprintf都不会这样做?
不能保证不会发生,但是我见过的大多数实现 tend to use a fixed size buffer for creating the formatted output string (a)(通常使用固定大小的缓冲区来创建格式化的输出字符串)。
就glibc而言(源代码在这里),stdio-common/vfprintf.c
内确实调用了malloc
,许多printf
家族在底层都使用它,所以如果我是你,我不会依赖它。甚至像sprintf
这样的字符串缓冲区输出调用,你可能认为不需要它,似乎也会在设置一些棘手的类似于FILE
的字符串句柄之后解析到该调用——参见libio/iovsprintf.c
。
我的建议是编写自己的代码来进行输出,以确保在幕后没有进行任何内存分配(当然希望write
本身不会这样做(不像*printf
会这样做))。由于你可能不会输出太多的转换内容(可能只是"Dang, I done run outta memory!
"),因此对格式化输出的需求应该是有问题的。
(a) C99环境考虑给出了一个提示,即至少有一些早期的实现具有缓冲限制。从我对Turbo C的记忆来看,我认为4K左右是极限,确实,C99规定(在7.19.6.1 fprintf
中):
任何单个转换产生的字符数都应至少为4095。
(C89的任务是将现有做法编码成标准,而不是创建一种新语言,这也是为什么一些这些最小值/最大值被放入标准的原因之一——它们被带入到后来的标准版本中)。
printf()
,而且没有使用任何缓冲区。 - DevSolarintmax_t
和一个指针。这就是一个缓冲区。用递归来隐藏它并不能让缓冲区消失。(而且,对于大于两位数的整数,一个普通的char
缓冲区所占用的空间会更小) - Billy ONealC标准并不保证fprintf
在底层不会调用malloc
。实际上,它对覆盖malloc
时会发生什么事情也没有任何保证。您应该参考特定C库的文档,或编写自己类似于fprintf
的函数,直接进行系统调用,避免任何堆分配的可能性。
malloc
的函数是那些由POSIX标记为async-signal-safe的函数。由于malloc
不要求是async-signal-safe,而且基本上不可能使其成为可用但效率低下的async-signal-safe函数,因此通常情况下,async-signal-safe函数不能调用它。printf
函数(包括fprintf
和甚至snprintf
)可以并且将使用malloc
来处理某些(全部?)格式字符串。malloc
总是 非法的(UB),当然... :-) - R.. GitHub STOP HELPING ICE
malloc()
,当分配失败时,我希望该函数打印一个日志消息。 - Adrian Ratnapalamalloc()
失败了,你怎么能继续程序呢?我猜你唯一能做的就是在文本中打印预定义的消息并使用write()
发送它。通常,现代软件中的分配失败都被视为“在分配失败时调用abort()
”。如果这是用于调试/诊断,核心转储将比任何错误消息告诉您更多(除非您当然已经破坏了堆栈)。 - Ethourisprintf()
来实现,或者我必须坚持使用write()
。 - Adrian Ratnapalaprintf()
很可能会调用malloc()
。 - Ethouris