内存不足时如何输出一些内容?
我有一组自定义的 malloc[、realloc 和 calloc] 和 free 函数。目前,该项目仅将它们用作函数普通版本的包装器。这些包装器函数会终止程序并应提供输出以指示错误。
目前输出错误消息的函数如下所示:
#ifdef __linux__
void memory_error() {
if (errno == ENOMEM)
printf("%s\n", "Out of memory or memory is limited. Fatal error. The program needs to terminate.");
else
printf("%s\n", "Memory allocation failed. Fatal error. The program needs to terminate.");
}
#else
void memory_error() {
printf("%s\n", "Memory allocation failed, likely due to being out of "
"memory or memory being limited for this program. "
"Fatal error. The program needs to terminate.");
}
#endif
问题是printf()
有时会分配内存,如果内存不足,就会失败。会fwrite()
分配内存吗?如果是这样,是否有一个可移植的(因此没有写入系统调用)选项来输出某些内容而无需分配更多内存?
到目前为止,作为 Unix 系统的有效解决方案,我可以这样做:
#ifdef __unix__
#define write_str_no_alloc(str) write(STDERR_FILENO, str, sizeof(str))
#else
#define write_str_no_alloc(str) ???
#endif
我缺少适用于 Windows 的解决方案。我更希望有一个适用于两者的通用解决方案,但这对我来说是可行的。
8
最佳答案
3
在 POSIX 系统上,该write
函数直接调用write
系统调用,因此不会发生内存分配。
Windows 有一个_write
函数,它是 POSIX 兼容层的一部分,并且也有:
这些函数直接调用操作系统来执行比流 I/O 提供的更低级别的操作。低级输入和输出调用不会缓冲或格式化数据。
因此你可以这样做:
#ifdef _MSC_VER
#include <io.h>
#define write_str_no_alloc(str) _write(2, str, sizeof(str))
#else
#define write_str_no_alloc(str) write(STDERR_FILENO, str, sizeof(str))
#endif
请注意,这要求参数是字符串文字或数组,否则sizeof
不会给出所需的结果。
6
-
它是否在程序的堆上分配内存?
– -
不太可能,但这可能是你能做的最好的事情了。
– -
我个人会用于
WriteFile
Windows。
– -
一旦我能够使用 Windows 机器或者其他人能帮我测试一下,我就会将此标记为已解决。遗憾的是,我认为 MS 文档中没有提到相关行为。尽管
WriteFile
提到了输出缓冲区。
– -
MS 文档提到不使用缓冲区
_write
。所以我将采用这种方式。谢谢!
–
|
您可以编写自己的safe_printf()
函数,该函数永远不会调用malloc()
。来自我的问答::
这是一个永远不会调用
safe_printf()
的函数!malloc()
我最终编写了一个
safe_printf()
从不调用的函数malloc()
,以防有人需要它。我已经测试过了,它在里面运行良好malloc()
。它使用write()
系统调用(在 Linux 上可用,但在 std C 中不可用)将字符写入 stdout。这里是:
…
#define SAFE_PRINTF_BUF_SIZE 2048 __attribute__((__format__(printf, 1, 2))) int safe_printf(const char *format, ...) {
…
只需将write()
我的safe_print()
函数替换为函数,它便可在 Windows 和 Linux 中运行。或者,使用 Windows 的,如。
获取代码。
用法与 完全相同printf()
。
示例(根据):
safe_printf("Failed to get a timestamp. errno = %i: %s\n",
errno, strerror(errno));
3
-
确定
snvprintf
不会分配任何内存吗?因为 @dbush 的答案已经足够了,并且每个使用的函数都记录为不分配内存。这里也是这种情况吗?
– -
printf()
mallocs,因为除了它分配的内存位置外,没有地方可以写入格式化的字符串。vsnprintf()
将格式化的字符串写入您提供的内存位置。但是,C 标准可能无法保证这一点,并且它可能基于您正在使用的标准库实现。
– -
1Sraples 我也是这么想的。我想在为项目构建日志记录功能时会重新考虑这一点。目前使用就足够了
write/_write
。在最坏的情况下,我必须自己进行格式化或不允许格式化非分配日志记录。
–
|
如果最终选择是printf()
(输出到stdout
),请务必跟进fflush(stdout)
以确保它可以输出。
特别是在错误情况下以及有关刷新的许多规则中,最好将此消息发送出去。
2
-
我最后写了个换行符,这也会刷新输出缓冲区。更重要的是,printf 不满足要求。讽刺的是, 的存在暗示了这一点
fflush
。
– -
@Tenobaal “最后写一个换行符,这也会刷新输出缓冲区。”–>。
–
|
puts
改用。–
puts
不会在任何主要系统上分配缓冲区吗?如果是这样,你能给我至少 linux 和 windows 的源代码吗?–
stderr
而不是stdout
(即使用fprintf
而不是printf
,或者更确切地说fputs
而不是puts
),因为stderr
通常不带缓冲。这将使尝试分配缓冲区的可能性降低。–
stderr
而不是stdout
,我也推荐使用fputs
而不是fprintf
。我猜就分配内存而言,fwrite
相当于。fputs
–
stderr
)是无缓冲的。但是,并不要求这样做。据我所知,并未stderr
说明是否如此。–
|