C语言 如何检测malloc失败?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6325940/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 08:54:19  来源:igfitidea点击:

How detect malloc failure?

c

提问by pic11

What is the portable way to check whether mallocfailed to allocate non-zero memory block?

检查是否malloc分配非零内存块失败的可移植方法是什么?

回答by a3nm

According to the Single Unix Specification, mallocwill return NULLand set errnowhen it fails.

根据Single Unix Specification,失败时malloc将返回NULL并设置errno

回答by Swift

I always do this:

我总是这样做:

tok = malloc( sizeof( char ) * ( strlen(tc) + 1 ) );

if( tok == NULL )
{
     /* Malloc failed, deal with it */
}

Some people do tok = (type) malloc( ... )but you should cast the result because apparently it covers up some nasty errors. I will do some research and see if I can find out exactly what they are.

有些人这样做,tok = (type) malloc( ... )但您应该转换结果,因为显然它掩盖了一些令人讨厌的错误。我会做一些研究,看看我是否能确切地找出它们是什么。

Edit:

编辑:

Casting malloc can hide a missing #include <stdlib.h>

铸造 malloc 可以隐藏丢失的 #include <stdlib.h>

I found this link which contained a very good explanation:

我发现这个链接包含一个很好的解释:

http://cboard.cprogramming.com/faq-board/25799-faq-casting-malloc.html

"So when you say this (char*)malloc(10)

You're saying that you take whatever malloc returns, convert it to a char*, and assign that to the variable in question.

This is all well and good if malloc is prototyped properly (by including stdlib.h), where it's defined as returning void*.

The problem comes in when you fail to include stdlib.h, and the compiler initially assumes that malloc returns an int. The real problem is, you DONT get any warning from the compiler.

You merrily then convert that int to a char* (via the cast). On machines where sizeof(char*) is different from sizeof(int), the code is seriously broken.

Now if you just have char *var = malloc( 10 ); And you miss out the include , you will get a warning from the compiler."

http://cboard.cprogramming.com/faq-board/25799-faq-casting-malloc.html

“所以当你说这个 (char*)malloc(10)

您是说您获取 malloc 返回的任何内容,将其转换为 char*,并将其分配给相关变量。

如果 malloc 原型正确(通过包括 stdlib.h),这一切都很好,它被定义为返回 void*。

当您未能包含 stdlib.h 时,问题就出现了,并且编译器最初假定 malloc 返回一个 int。真正的问题是,你不会从编译器那里得到任何警告。

然后您愉快地将该 int 转换为 char* (通过演员表)。在 sizeof(char*) 与 sizeof(int) 不同的机器上,代码严重损坏。

现在如果你只有 char *var = malloc( 10 ); 如果您错过了 include ,您将收到编译器的警告。”

回答by David Leonard

You can detect failure when:

您可以在以下情况下检测故障:

malloc(n)returns NULL

malloc(n)返回 NULL

This is the most common and reliable test to detect an allocation failure. If you want to be portable beyond POSIX/SUS, I wouldn't trust errnothough. If you need detail, say for logging, I'd zero errnobefore the call, see if it changed, then maybe log that.

这是检测分配失败的最常见和最可靠的测试。如果您想在 POSIX/SUS 之外具有可移植性,我不会相信errno。如果您需要详细信息,例如记录,我会errno在通话前归零,看看它是否发生了变化,然后记录下来。

malloc(n)returns a non-NULLaddress which is not backed by actual memory

malloc(n)返回一个NULL不受实际内存支持的非地址

Touch it and see if you get killed by the OS. Yes, this can happen. It's called memory overcommitand resembles fractional reserve banking. It's the optimistic approach of an OS or hypervisor to return addresses to virtual memory they're gambling they won't ever have to actually provide. This happens on Linux, VMware. (I can't find any explicit evidence of Windows overcommitting, although requested pages are only "committed" when they are touched.)

触摸它,看看您是否被操作系统杀死。是的,这可能发生。它被称为内存过量使用,类似于部分准备金银行业务。这是操作系统或虚拟机管理程序的乐观方法,将地址返回到他们赌博的虚拟内存,他们将永远不必实际提供。这发生在LinuxVMware 上。(我找不到任何关于 Windows 过度提交的明确证据,尽管请求的页面仅在被触摸时才“提交”。)

The question then is "how do I portably detect if my program is about to crash on accessing an address I got from the malloc I previously trusted like a teenage crush?". One way might be to read()a random file into the test areaand see if the OS returns EINVAL or equivalent.

那么问题是“我如何可移植地检测我的程序是否会在访问我从以前信任的 malloc 获得的地址时崩溃?”。一种方法可能是将read()随机文件放入测试区域,然后查看操作系统是否返回 EINVAL 或等效项。

For extra points,

对于加分,

malloc(0)returns NULLand leaves errnoundefined

malloc(0)返回NULL并离开errno未定义

I know the question asked for "non-zero [sized] memory block", but this is interesting. Consider a SUS-compliant allocator that intendsto return non-NULLfor a zero-sized allocation (it can do that), but then it fails, so it has to return NULL. And it could try to set errno. Is that a failure? I think Hoare says we paid a billion dollars for this ambiguity. So, calling malloc(0)is not portable and the questioner probably knew that!

我知道问题要求“非零 [大小] 内存块”,但这很有趣。考虑一个符合 SUS 的分配器,它打算NULL为零大小的分配返回 non- (它可以做到这一点),但是它失败了,所以它必须返回NULL. 它可以尝试设置errno. 那是失败吗?我认为霍尔说我们为这种模棱两可支付了 10 亿美元。所以,呼叫malloc(0)是不可移植的,提问者可能知道这一点!

回答by Stephen C

Sure. The portable way is to test if malloc(...)returns NULL.

当然。可移植的方法是测试是否malloc(...)返回NULL

回答by chux - Reinstate Monica

malloc(n)returns NULLon failure.
malloc(0)mayreturn NULL.

malloc(n)NULL失败返回。
malloc(0)可能会回来NULL

To detect failure:

检测故障:

void* ptr = malloc(n);
if (ptr == NULL && n > 0) Handle_Failure();


Notes:

笔记:

As in OP's case: "... allocate non-zero memory block", often code is such that a 0allocation request can not occur and so the 0test is not needed.

就像在 OP 的情况下一样:“...分配非零内存块”,通常代码是这样的,0分配请求不会发生,因此0不需要测试。

size_t nstr = strlen(some_string) + 1;
void* ptrstr = malloc(nstr);
if (ptrstr == NULL) Handle_Failure();

Some systems set errnoon failure, but not all. Setting errnodue to memory allocation failure is notspecified in the C11 spec.

一些系统设置errno失败,但不是全部。C11 规范中指定errno由于内存分配失败而导致的设置。

malloc(n)expects nto be the unsigned type size_t. Using an int nwith a negative value will certainly convert to some large unsigned value and then likely fail the memory allocation.

malloc(n)期望n是无符号类型size_t。使用int n负值肯定会转换为一些大的无符号值,然后可能会导致内存分配失败。