为什么不malloc的工作有时会? [英] Why does malloc not work sometimes?

查看:309
本文介绍了为什么不malloc的工作有时会?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的Linux移植到Windows一个C项目。在Linux中是完全稳定。在Windows上,它的工作好大部分时间,但有时我得到一个分段错误。

I'm porting a C project from Linux to Windows. On Linux it is completely stable. On Windows, it's working well most times, but sometimes I got a segmentation fault.

我使用Microsoft Visual Studio 2010的编译和调试,看起来像我有时叫的malloc根本不分配内存,返回NULL。该机拥有的可用内存;它已经通过code一千次了,但它仍然在不同的地点发生的。

I'm using Microsoft Visual Studio 2010 to compile and debug and looks like sometimes my malloc calls simply doesn't allocate memory, returning NULL. The machine has free memory; it already passed through that code a thousand times, but it still happens in different locations.

就像我说的,它不发生的时间或在同一位置;它看起来像一个随机误差。

Like I said, it doesn't happen all the time or in the same location; it looks like a random error.

有什么我必须要在Windows比Linux上更小心?我能是做错了?

Is there something I have to be more careful on Windows than on Linux? What can I be doing wrong?

推荐答案

的malloc()时,它无法服务于内存请求返回NULL的无效的指针。在大多数情况下的C内存分配程序管理列表或内存的可用内存堆通过调用操作系统分配的内存额外块时,的malloc()调用时并没有列表或堆满足请求上的块

malloc() returns an invalid pointer of NULL when it is unable to service a memory request. In most cases the C memory allocation routines manage a list or heap of memory available memory with calls to the operating system to allocate additional chunks of memory when a malloc() call is made and there is not a block on the list or heap to satisfy the request.

所以第一案的malloc()失败是当内存请求不能被满足,因为没有记忆列表或堆和时可使用的块C运行时内存管理要求更多的内存从操作系统,请求被拒绝了。

So the first case of malloc() failing is when the memory request can not be satisfied because there is not a usable block of memory on the list or heap and when the C runtime memory management requested more memory from the operating system, the request was refused.

下面是关于指针分配策略的文章。

本论坛文章给出的malloc失败的例子,由于内存碎片

另一个原因,的malloc()可能会失败,是因为内存管理数据结构已成为可能损坏,由于缓冲区溢出。不同版本的的malloc()可以使用的内存管理和确定多少内存,以提供不同的策略时,的malloc()叫做。例如,一个的malloc()可能会给你请求的字节数完全或者它可能会给你超过你要求,以适应内部存储器的边界或分配的块使内存管理更容易。

Another reason why malloc() might fail is because the memory management data structures have become corrupted probably due to a buffer overflow. Different versions of malloc() can use different strategies for memory management and determining how much memory to provide when malloc() is called. For instance a malloc() may give you exactly the number of bytes requested or it may give you more than you asked for in order to fit the block allocated within memory boundaries or to make the memory management easier.

随着现代操作系统和虚拟内存,它是pretty难以耗尽内存,除非你正在做一些非常大的内存驻留存储。然而,由于用户Yeow_Meng在下面的评论中提到,如果你正在做算术的大小来确定分配,其结果是你可能最终会请求大量的内存,因为参数的malloc负数( )为内存分配量是无符号的。

With modern operating systems and virtual memory, it is pretty difficult to run out of memory unless you are doing some really large memory resident storage. However as user Yeow_Meng mentioned in a comment below, if you are doing arithmetic to determine the size to allocate and the result is a negative number you could end up requesting a huge amount of memory because the argument to malloc() for the amount of memory to allocation is unsigned.

您可以做指针运算时,确定多少空间是需要一些数据运行到负尺寸的问题。这种类型的错误是因为这是对文本是意外完成文本解析常见。例如,下面的code会导致非常大的的malloc()请求。

You can run into the problem of negative sizes when doing pointer arithmetic to determine how much space is needed for some data. This kind of error is common for text parsing that is done on text that is unexpected. For example the following code would result in a very large malloc() request.

char pathText[64] = "./dir/prefix";  // a buffer of text with path using dot (.) for current dir
char *pFile = strrchr (pathText, '/');  // find last slash where the file name begins
char *pExt = strrchr (pathText, '.');    // looking for file extension 

// at this point the programmer expected that
//   - pFile points to the last slash in the path name
//   - pExt point to the dot (.) in the file extension or NULL
// however with this data we instead have the following pointers because rather than
// an absolute path, it is a relative path
//   - pFile points to the last slash in the path name
//   - pExt point to the first dot (.) in the path name as there is no file extension
// the result is that rather than a non-NULL pExt value being larger than pFile,
// it is instead smaller for this specific data.
char *pNameNoExt;
if (pExt) {  // this really should be if (pExt && pFile < pExt) {
    // extension specified so allocate space just for the name, no extension
    // allocate space for just the file name without the extension
    // since pExt is less than pFile, we get a negative value which then becomes
    // a really huge unsigned value.
    pNameNoExt = malloc ((pExt - pFile + 1) * sizeof(char));
} else {
    pNameNoExt = malloc ((strlen(pFile) + 1) * sizeof(char));
}

有一个良好的运行时内存管理会尽量合并的内存释放块使许多更小的块将被合并成更大的块,因为他们被释放。该内存块的结合降低了暂时无法使用的是已有的列表或内存堆在由C内存管理运行时被成功地服务于内存请求的机会。

A good run time memory management will try to coalesce freed chunks of memory so that many smaller blocks will be combined into larger blocks as they are freed. This combining of chunks of memory reduces the chances of being unable to service a memory request using what is already available on the list or heap of memory being managed by the C memory management run time.

越多,你可以只重用已分配的内存,你依赖于的malloc()少免费()越好。如果你不是做的malloc()那么就很难为它失败。

The more that you can just reuse already allocated memory and the less you depend on malloc() and free() the better. If you are not doing a malloc() then it is difficult for it to fail.

这可以改变许多小规模呼叫的malloc()较少的大型呼叫的malloc()的更多的机会就越少,你有分裂的内存和扩展内存列表或堆有很多,因为他们不相邻无法合并小块的大小。

The more that you can change many small size calls to malloc() to fewer large calls to malloc() the less chance you have for fragmenting the memory and expanding the size of the memory list or heap with lots of small blocks that can not be combined because they are not next to each other.

越多,你可以的malloc()免费()在同一时间连续的块,越可能是内存管理的运行时间可以合并块。

The more that you can malloc() and free() contiguous blocks at the same time, the more likely that the memory management run time can coalesce blocks.

有没有规定说你必须做一个的malloc()与特定的大小。所以,你可能想使用某种呼叫的规则,以的malloc()这样的标准大小的块分配,让你使用类似的公式中的16字节的块分配((大小/ 16)+1)* 16或更可能((大小>> 4)+ 1) - ;&下; 4.许多脚本语言使用类似的东西,以增加一再呼吁的机会,的malloc()免费()能够匹配的内存列表或堆在一个空闲块的请求。

There is no rule that says you must do a malloc() with a specific size. So you may want to use some kind of a rule for calls to malloc () so that standard sized blocks are allocated so that you allocate in blocks of 16 bytes using a formula like ((size / 16) + 1) * 16 or more likely ((size >> 4) + 1) << 4. Many script languages use something similar so as to increase the chance of repeated calls to malloc() and free() being able to match up a request with a free block on the list or heap of memory.

下面是试图减少分配和解除分配的块的数量稍微简单的例子。比方说,我们有记忆可变大小块的链接列表。因此,结构在链表的样子有点像节点:

Here is a somewhat simple example of trying to reduce the number of blocks allocated and deallocated. Lets say that we have a linked list of variable sized blocks of memory. So the struct for the nodes in the linked list look something like:

typedef struct __MyNodeStruct {
    struct __MyNodeStruct *pNext;
    unsigned char *pMegaBuffer;
} MyNodeStruct;

有可能是为特定的缓冲区和它的节点分配此内存的两种方式。第一是节点后跟缓冲器的分配如在下面的标准分配

There could be two ways of allocating this memory for a particular buffer and its node. The first is a standard allocation of the node followed by an allocation of the buffer as in the following.

MyNodeStruct *pNewNode = malloc(sizeof(MyNodeStruct));
if (pNewNode)
    pNewNode->pMegaBuffer = malloc(15000);

不过另一种办法是做这样的事情,它使用一个单一的内存分配与指针运算以下,这样一个的malloc()同时提供存储区。

MyNodeStruct *pNewNode = malloc(sizeof(myNodeStruct) + 15000);
if (pNewNode)
    pNewNode->pMegaBuffer = ((unsigned char *)pNewNode) + sizeof(myNodeStruct);

然而,如果你正在使用这种单一的分配方法,你需要确保你是在使用指针的一致 pMegaBuffer ,你不小心做了免费()就可以了。如果您有更大的缓冲区改变了缓冲区,你需要释放的节点,并重新分配缓冲区和节点。因此对于程序员更多的工作。

However if you are using this single allocation method, you will need to make sure that you are consistent in the use of the pointer pMegaBuffer that you do not accidently do a free() on it. And if you are having to change out the buffer with a larger buffer, you will need to free the node and reallocate buffer and node. So there is more work for the programmer.

这篇关于为什么不malloc的工作有时会?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆