xmalloc和malloc有什么区别?

vai*_*war 46 c

xmalloc()malloc()内存分配有什么区别?
有没有使用的专家xmalloc()

orl*_*rlp 64

xmalloc()是一个非标准的功能,其座右铭是成功或死亡.如果它无法分配内存,它将终止您的程序并打印错误消息stderr.

分配本身也不例外; 只有在没有内存可以分配的情况下的行为是不同的.

使用malloc(),因为它更友好和标准.


R..*_*R.. 26

xmalloc不属于标准库.它通常是懒惰程序员非常有害的函数的名称,这在许多GNU软件中很常见,abort如果malloc失败则会调用它们.根据程序/库的不同,它也可以转换malloc(0)malloc(1)确保xmalloc(0)返回唯一指针.

在任何情况下,abort荷兰国际集团的malloc失败是非常非常恶劣的行为,特别是对库中的代码.其中一个最臭名昭着的例子是GMP(GNU多精度算术库),它会在计算机内存不足时中止调用程序.

正确的库级代码应该始终通过退出它在中间的任何部分完成的操作并将错误代码返回给调用者来处理分配失败.然后,调用程序可以决定要做什么,这可能涉及保存关键数据.

  • 调用使用`xmalloc()`'懒惰程序员'的开发人员是不公平的.检测分配错误[并非总是可行](http://www.win.tue.nl/~aeb/linux/lk/lk-9.html#ss9.6).如果您的目标操作系统是一个`malloc()`(基本上)_never failed_由于过度使用启用?那么,通过检查`malloc()`的返回值来膨胀您的代码库是不是浪费时间和金钱?为游戏编写一个内部关卡编辑器就好像它是一个空中交通管制系统一样,只会增加成本而没有真正的好处.在安全关键系统之外,有时可能会"懒惰",恕我直言. (22认同)
  • @evadeflow:告诉丢失文件的人,因为他们不小心打开了一张太大而无法记忆的第二份文件(就在昨天发生在那个在这个问题上不相信我的人). (9认同)
  • 如果确实如此,那你做错了.序列化没有合法的需要使用任何新的分配. (6认同)
  • @evadeflow:这是应用程序级别的有效方法,但不是库级别的方法.库(例如glib)假设调用应用程序没有任何不关心丢失的非日志数据是不合理的.如果一个库将以这种方式运行,它应该突出地记录该要求,而不是将其隐藏在分配函数的文档中.当然他们不会这样做,因为没有人会故意使用这样记录的图书馆; 为了让人们使用这样一个低质量的图书馆你必须隐藏这个问题. (6认同)
  • 当然,"保存关键数据"以及调用程序可能想要做的其他任何事情也需要分配内存页面(即使你实际上没有自己分配,库函数也需要这样做).在任何情况下,我认为你很可能无法恢复. (4认同)
  • 我同意没有防止数据丢失的策略就是"懒惰".但是当`malloc()`失败并且仍然设法不丢失数据时,许多应用程序都会毫无歉意地终止(https://developer.gnome.org/glib/2.28/glib-Memory-Allocation.html#glib-Memory-Allocation.description)因为他们(例如)嵌入了SQLite和journal所有操作.当然,SQLite具有相当强大的(以及[经过良好测试](http://www.sqlite.org/testing.html#oomtesting))OOM检测,所以它发挥了你的观点,这是一个重要的问题.我宁愿别人解决它.这会让我变懒吗? (3认同)
  • 正如注释(不是说它是对还是错)一样,其他一些语言(即 Rust 的标准库)在 OOM 条件下(如果操作系统本身在此之前没有终止应用程序的话)会自然而然地出现恐慌或中止。 (3认同)
  • -pedantic:GCC 5.2调用`exit`而不是`abort`:http://stackoverflow.com/a/31556623/895245,它将运行`atexit`和GNU`xatexit`回调。 (2认同)
  • 我确实认为有很多简单的命令行工具使用此功能不会造成任何损害。只要没有可能留下不完整的外部状态(例如,重命名命令仅重命名一半文件),我认为如果系统内存不足,终止进程不会有什么危害。在命令“ls”中从失败的分配中恢复有什么好处?我认为部分打印的目录列表和“内存不足;中止”消息是完全可以接受的,并且可以安全地减少代码库的大小。 (2认同)

eva*_*low 19

正如其他人所提到的那样,它xmalloc经常被实现为一个包装函数,它调用操作系统提供的malloc和盲目的调用abort或者exit如果它失败了.但是,许多项目包含一个xmalloc在退出之前尝试保存应用程序状态的函数(例如,参见neovim).

就个人而言,我认为xmalloc这是一种特定于项目的扩展 malloc而不是退出 malloc.虽然我不记得曾经看到一个版本拉闸打电话abort或者exit,他们有的做了很多不止于此.

所以,这个问题的答案"有什么之间的区别xmallocmalloc是:这取决于xmalloc.是非标准,具体项目的功能,所以它可以做任何事情都知道肯定的唯一途径就是阅读代码.


小智 7

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;
}
Run Code Online (Sandbox Code Playgroud)

然后在你的代码头(早期)你放

#define malloc(m) xmalloc(m)

在编译之前默默地重写源代码.(您可以通过直接调用C预处理器并保存输出来查看重写的代码.)

如果您的程序崩溃不是您想要的,您可以做一些不同的事情

  • 使用垃圾收集器
  • 重新设计你的代码,减少内存耗费
  • 有错误检查程序中的代码,以正常处理内存不足或其他分配错误.

用户不喜欢将他们的数据丢失到程序中的内置崩溃命令.

  • @thb 在专门的应用程序中它可能会很好。当然,它并不适用于所有情况,但在某些情况下它效果很好。另外...嗯,语言运行时中的垃圾收集是 C 中的垃圾收集,因为运行时本身是用 C 编写的。 (2认同)

Cir*_*四事件 7

xmalloc 是libiberty的一部分

https://gcc.gnu.org/onlinedocs/libiberty/index.html这是一个GNU utils库.

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);
}
Run Code Online (Sandbox Code Playgroud)

正如其他人所提到的那样,非常简单:

  • 尝试 malloc
  • 如果失败了
    • 打印错误消息
    • 呼叫 exit