xmalloc()
和malloc()
在内存分配上有什么区别?
使用xmalloc()
有什么优点吗?
xmalloc()
是一种非标准的函数,其座右铭是“成功或死亡”。如果它无法分配内存,它将终止您的程序并向stderr
打印错误消息。
分配本身没有区别; 只有在无法分配内存的情况下行为不同。
请使用 malloc()
,因为它更友好和标准化。
xmalloc
,然后就这样了。或者说,使用任何对你的情况有意义的方法。例如,如果我正在为特定的操作系统编写程序,并且在OOM时不会丢失数据,那么使用xmalloc
是有意义的。 - legends2kxmalloc
不是标准库的一部分,通常是一个对懒惰程序员非常有害的函数名称,常见于许多GNU软件中,如果malloc
失败,则调用abort
。根据程序/库的不同,它可能还会将malloc(0)
转换为malloc(1)
,以确保xmalloc(0)
返回一个唯一的指针。
无论如何,在malloc
失败时使用abort
行为都非常糟糕,特别是对于库代码而言。最臭名昭著的例子之一是GMP(GNU多精度算术库),每当计算运行出现内存不足时就会中止调用程序。
正确的库级代码应始终通过回退任何部分完成的操作并向调用者返回错误代码来处理分配失败。然后,调用程序可以决定要做什么,这可能涉及保存关键数据。
保存关键数据
和调用程序可能需要的几乎所有其他操作都需要分配内存页(即使您实际上不进行分配,库函数也需要这样做)。我不认为在任何情况下你都有很大可能性可以恢复。 - Frerich Raabexmalloc()
的开发人员为“懒惰的程序员”是不公平的。检测分配错误并非总是可能的。如果你的目标操作系统启用了超额提交,导致malloc()
(实质上)几乎从不失败,那么将代码基础充斥着对malloc()
返回值的检查是否是一种浪费时间和金钱?在为游戏编写内部级别编辑器时,将其编写得像空中交通管制系统一样只会增加成本,而没有任何真正的好处。在安全关键的系统之外,有时放松一下也是可以的,我个人认为。 - evadeflowexit
,而不是 abort
: https://dev59.com/22sz5IYBdhLWcg3w5MA0#31556623,这将运行 atexit
和 GNU xatexit
回调函数。 - Ciro Santilli OurBigBook.comxmalloc
很常被实现为一个调用操作系统提供的 malloc
的包装函数,并且如果失败了就会盲目地调用 abort
或者 exit
。然而,许多项目包含一个在退出之前尝试保存应用程序状态的 xmalloc
函数(例如请看 neovim)。xmalloc
是一种特定于项目的扩展版的 malloc
,而不是退出版的 malloc
。虽然我不记得曾经看过一个没有最终调用 abort
或者 exit
的版本,但是有些版本做了更多的事情。xmalloc
和 malloc
之间的区别是什么 ":这取决于情况。 xmalloc
是一个非标准的、特定于项目的函数,所以它可以做任何事情。唯一确定的方法是阅读代码。xmalloc
是libiberty的一部分
https://gcc.gnu.org/onlinedocs/libiberty/index.html是GNU工具库。
malloc
是ANSI C。
xmalloc
经常被包含在许多重要的GNU项目中,包括GCC和Binutils,两者都大量使用它。但是,也可以将其构建为动态库以在您的程序中使用。例如,Ubuntu有libiberty-dev
软件包。
xmalloc
的文档位于:https://gcc.gnu.org/onlinedocs/libiberty/Functions.html,在GCC 5.2.0上实现为libiberty/xmalloc.c
PTR
xmalloc (size_t size)
{
PTR newmem;
if (size == 0)
size = 1;
newmem = malloc (size);
if (!newmem)
xmalloc_failed (size);
return (newmem);
}
void
xmalloc_failed (size_t size)
{
#ifdef HAVE_SBRK
extern char **environ;
size_t allocated;
if (first_break != NULL)
allocated = (char *) sbrk (0) - first_break;
else
allocated = (char *) sbrk (0) - (char *) &environ;
fprintf (stderr,
"\n%s%sout of memory allocating %lu bytes after a total of %lu bytes\n",
name, *name ? ": " : "",
(unsigned long) size, (unsigned long) allocated);
#else /* HAVE_SBRK */
fprintf (stderr,
"\n%s%sout of memory allocating %lu bytes\n",
name, *name ? ": " : "",
(unsigned long) size);
#endif /* HAVE_SBRK */
xexit (1);
}
/* This variable is set by xatexit if it is called. This way, xmalloc
doesn't drag xatexit into the link. */
void (*_xexit_cleanup) (void);
void
xexit (int code)
{
if (_xexit_cleanup != NULL)
(*_xexit_cleanup) ();
exit (code);
}
正如其他人所提到的那样,这非常简单:
malloc
exit
K&R C 中xmalloc.c的一个原始示例
#include <stdio.h>
extern char *malloc ();
void *
xmalloc (size)
unsigned size;
{
void *new_mem = (void *) malloc (size);
if (new_mem == NULL)
{
fprintf (stderr, "fatal: memory exhausted (xmalloc of %u bytes).\n", size);
exit (-1);
}
return new_mem;
}
然后在您的代码头(早期)中放置
#define malloc(m) xmalloc(m)
以在编译之前静默地重写源代码。 (您可以直接调用C预处理器并保存输出来查看重写的代码。)
如果崩溃您的程序不是您想要的,您可以采取不同的方法:
用户不喜欢由于程序内置的崩溃命令而丢失他们的数据。
malloc()
存在于标准 C 中。xmalloc()
不存在。这个xmalloc()
函数定义在哪里? - Keith Thompsonxmalloc
?这两者的主要区别是malloc
是C标准的一部分,而xmalloc
不是。 - Praetorian