简体   繁体   English

malloc()和free()如何工作?

[英]How do malloc() and free() work?

I want to know how malloc and free work. 我想知道mallocfree工作的方式。

int main() {
    unsigned char *p = (unsigned char*)malloc(4*sizeof(unsigned char));
    memset(p,0,4);
    strcpy((char*)p,"abcdabcd"); // **deliberately storing 8bytes**
    cout << p;
    free(p); // Obvious Crash, but I need how it works and why crash.
    cout << p;
    return 0;
}

I would be really grateful if the answer is in depth at memory level, if it's possible. 如果可能的话,我很感激如果答案在内存级别。

OK some answers about malloc were already posted. 确定有关malloc的一些答案已经发布。

The more interesting part is how free works (and in this direction, malloc too can be understood better). 更加有趣的部分是自由的工作方式 (在这个方向上,也可以更好地理解malloc)。

In many malloc/free implementations, free does normally not return the memory to the operating system (or at least only in rare cases). 在许多malloc / free实现中,free通常不会将内存返回给操作系统(或至少仅在极少数情况下)。 The reason is that you will get gaps in your heap and thus it can happen, that you just finish off your 2 or 4 GB of virtual memory with gaps. 原因是您将在堆中留下间隙,因此可能发生,您只需用间隙完成2或4 GB的虚拟内存即可。 This should be avoided, since as soon as the virtual memory is finished, you will be in really big trouble. 应该避免这种情况,因为一旦虚拟内存完成,您就会遇到很大的麻烦。 The other reason is, that the OS can only handle memory chunks that are of a specific size and alignment. 另一个原因是,操作系统只能处理具有特定大小和对齐方式的内存块。 To be specific: Normally the OS can only handle blocks that the virtual memory manager can handle (most often multiples of 512 bytes eg 4KB). 具体来说:通常,操作系统只能处理虚拟内存管理器可以处理的块(通常是512字节的倍数,例如4KB)。

So returning 40 Bytes to the OS will just not work. 因此,将40字节返回到操作系统将无法正常工作。 So what does free do? 那么免费做什么?

Free will put the memory block in its own free block list. Free将把内存块放在其自己的空闲块列表中。 Normally it also tries to meld together adjacent blocks in the address space. 通常,它还会尝试将地址空间中的相邻块融合在一起。 The free block list is just a circular list of memory chunks which have some administrative data in the beginning. 空闲块列表只是存储块的循环列表,这些存储块的开头具有一些管理数据。 This is also the reason why managing very small memory elements with the standard malloc/free is not efficient. 这也是为什么使用标准malloc / free管理非常小的内存元素效率不高的原因。 Every memory chunk needs additional data and with smaller sizes more fragmentation happens. 每个内存块都需要其他数据,而较小的内存块会发生更多碎片。

The free-list is also the first place that malloc looks at when a new chunk of memory is needed. 当需要新的内存块时,空闲列表也是malloc查找的第一位。 It is scanned before it calls for new memory from the OS. 在从操作系统调用新内存之前,将对其进行扫描。 When a chunk is found that is bigger than the needed memory, it is divided into two parts. 当发现一块大于所需内存的块时,它将分为两部分。 One is returned to caller, the other is put back into the free list. 一个返回给呼叫者,另一个返回到空闲列表。

There are many different optimizations to this standard behaviour (for example for small chunks of memory). 此标准行为有许多不同的优化(例如,用于一小块内存)。 But since malloc and free must be so universal, the standard behaviour is always the fallback when alternatives are not usable. 但是,由于malloc和free必须如此通用,因此当替代方法不可用时,标准行为始终是后备。 There are also optimizations in handling the free-list — for example storing the chunks in lists sorted by sizes. 在处理空闲列表时也有一些优化,例如,将块存储在按大小排序的列表中。 But all optimizations also have their own limitations. 但是所有优化也都有其自身的局限性。

Why does your code crash: 为什么您的代码崩溃:

The reason is that by writing 9 chars (don't forget the trailing null byte) into an area sized for 4 chars, you will probably overwrite the administrative-data stored for another chunk of memory that resides "behind" your chunk of data (since this data is most often stored "in front" of the memory chunks). 原因是,通过将9个字符(不要忘记尾随的空字节)写入大小为4个字符的区域中,您可能会覆盖存储在另一块数据“后面”的另一块内存所存储的管理数据(因为此数据通常存储在内存块的“前面”。 When free then tries to put your chunk into the free list, it can touch this administrative-data and therefore stumble over an overwritten pointer. 当空闲时,然后尝试将您的块放入空闲列表中,它可以触摸此管理数据,因此偶然发现了一个覆盖的指针。 This will crash the system. 这将使系统崩溃。

This is a rather graceful behaviour. 这是一个相当优雅的行为。 I have also seen situations where a runaway pointer somewhere has overwritten data in the memory-free-list and the system did not immediately crash but some subroutines later. 我还看到过这样的情况,即某个地方的失控指针已覆盖了无内存列表中的数据,并且系统并没有立即崩溃,而是在以后出现了一些子例程。 Even in a system of medium complexity such problems can be really, really hard to debug! 即使在中等复杂度的系统中,此类问题也确实非常难以调试! In the one case I was involved, it took us (a larger group of developers) several days to find the reason of the crash -- since it was in a totally different location than the one indicated by the memory dump. 在我参与的一个案例中,我们(一大批开发人员)花了几天的时间来找出崩溃的原因-因为它所处的位置与内存转储所指示的位置完全不同。 It is like a time-bomb. 就像定时炸弹一样。 You know, your next "free" or "malloc" will crash, but you don't know why! 您知道,您的下一个“免费”或“ malloc”将崩溃,但您不知道为什么!

Those are some of the worst C/C++ problems, and one reason why pointers can be so problematic. 这些是一些最严重的C / C ++问题,也是指针如此有问题的原因之一。

As aluser says in this forum thread : 正如aluser在这个论坛主题中所说:

Your process has a region of memory, from address x to address y, called the heap. 您的进程具有从地址x到地址y的内存区域,称为堆。 All your malloc'd data lives in this area. 您所有分配的数据都位于该区域中。 malloc() keeps some data structure, let's say a list, of all the free chunks of space in the heap. malloc()保留了堆中所有空闲空间的一些数据结构,例如一个列表。 When you call malloc, it looks through the list for a chunk that's big enough for you, returns a pointer to it, and records the fact that it's not free any more as well as how big it is. 当您调用malloc时,它将在列表中查找对您来说足够大的块,并返回指向该块的指针,并记录其不再释放以及释放了多少的事实。 When you call free() with the same pointer, free() looks up how big that chunk is and adds it back into the list of free chunks(). 当您使用相同的指针调用free()时,free()查找该块的大小,并将其重新添加到空闲chunks()的列表中。 If you call malloc() and it can't find any large enough chunk in the heap, it uses the brk() syscall to grow the heap, ie increase address y and cause all the addresses between the old y and the new y to be valid memory. 如果调用malloc()却在堆中找不到足够大的块,它将使用brk()系统调用来增加堆,即增加地址y并使旧y与新y之间的所有地址变为是有效的内存。 brk() must be a syscall; brk()必须是系统调用; there is no way to do the same thing entirely from userspace. 没有办法完全从用户空间执行相同的操作。

malloc() is system/compiler dependent so it's hard to give a specific answer. malloc()是依赖于系统/编译器的,因此很难给出具体的答案。 Basically however it does keep track of what memory it's allocated and depending on how it does so your calls to free could fail or succeed. 但是从根本上讲,它确实会跟踪分配的内存,并取决于其执行方式,因此对free的调用可能失败或成功。

malloc() and free() don't work the same way on every O/S.

One implementation of malloc/free does the following: malloc / free的一种实现方式执行以下操作:

  1. Get a block of memory from the OS through sbrk() (Unix call). 通过sbrk()(Unix调用)从操作系统获取一块内存。
  2. Create a header and a footer around that block of memory with some information such as size, permissions, and where the next and previous block are. 在该内存块周围创建页眉和页脚,并提供一些信息,例如大小,权限以及下一个和上一个块的位置。
  3. When a call to malloc comes in, a list is referenced which points to blocks of the appropriate size. 调用malloc时,将引用一个列表,该列表指向适当大小的块。
  4. This block is then returned and headers and footers are updated accordingly. 然后返回该块,并相应地更新页眉和页脚。

Memory protection has page-granularity and would require kernel interaction 内存保护具有页面粒度,需要内核交互

Your example code essentially asks why the example program doesn't trap, and the answer is that memory protection is a kernel feature and applies only to entire pages, whereas the memory allocator is a library feature and it manages .. without enforcement .. arbitrary sized blocks which are often much smaller than pages. 您的示例代码本质上询问了为什么示例程序不会捕获,答案是内存保护是内核功能,仅适用于整个页面,而内存分配器是库功能,它在不强制执行的情况下进行管理。大小的块,通常比页面小得多。

Memory can only be removed from your program in units of pages, and even that is unlikely to be observed. 只能以页为单位从程序中删除内存,即使这样也不太可能观察到。

calloc(3) and malloc(3) do interact with the kernel to get memory, if necessary. 如果需要,calloc(3)和malloc(3)会与内核进行交互以获取内存。 But most implementations of free(3) do not return memory to the kernel 1 , they just add it to a free list that calloc() and malloc() will consult later in order to reuse the released blocks. 但是大多数free(3)的实现都不会将内存返回给内核1 ,它们只是将其添加到freeoc列表中,calloc()和malloc()稍后将查询该列表以重用释放的块。

Even if a free() wanted to return memory to the system, it would need at least one contiguous memory page in order to get the kernel to actually protect the region, so releasing a small block would only lead to a protection change if it was the last small block in a page. 即使free()想要将内存返回给系统,它也至少需要一个连续的内存页才能使内核实际保护该区域,因此释放一个小块只会导致保护更改,如果它是页面中的最后一个小块。

So your block is there, sitting on the free list. 因此,您所在的块就在那儿,位于空闲列表上。 You can almost always access it and nearby memory just as if it were still allocated. 您几乎总是可以访问它和附近的内存,就像仍在分配它一样。 C compiles straight to machine code and without special debugging arrangements there are no sanity checks on loads and stores. C直接编译为机器代码,并且没有特殊的调试安排,就不会对装载和存储进行完整性检查。 Now, if you try and access a free block, the behavior is undefined by the standard in order to not make unreasonable demands on library implementators. 现在,如果您尝试访问一个空闲块,则该行为未由标准定义,以便不对库实现者提出不合理的要求。 If you try and access freed memory or meory outside an allocated block, there are various things that can go wrong: 如果您尝试访问已分配块之外的已释放内存或内存,则可能会出错:

  • Sometimes allocators maintain separate blocks of memory, sometimes they use a header they allocate just before or after (a "footer", I guess) your block, but they just might want to use memory within the block for the purpose of keeping the free list linked together. 有时分配器维护单独的内存块,有时他们使用在分配的块之前或之后分配的标头(我想是“页脚”),但他们可能只是想在块中使用内存以保持空闲列表的目的链接在一起。 If so, your reading the block is OK, but its contents may change, and writing to the block would be likely to cause the allocator to misbehave or crash. 如果是这样,则您阅读该块是可以的,但是其内容可能会更改,并且写入该块很可能会导致分配器行为异常或崩溃。
  • Naturally, your block may be allocated in the future, and then it is likely to be overwritten by your code or a library routine, or with zeroes by calloc(). 自然地,您的块可能会在将来分配,然后可能会被您的代码或库例程覆盖,或者被calloc()填充为零。
  • If the block is reallocated, it may also have its size changed, in which case yet more links or initialization will be written in various places. 如果重新分配了块,则它的大小也可能会更改,在这种情况下,还会在不同位置写入更多链接或初始化。
  • Obviously you may reference so far out of range that you cross a boundary of one of your program's kernel-known segments, and in this one case you will trap. 显然,您可能引用的范围太广,以至于超出了程序的内核已知段之一的边界,在这种情况下,您将陷入陷阱。

Theory of Operation 操作理论

So, working backwards from your example to the overall theory, malloc(3) gets memory from the kernel when it needs it, and typically in units of pages. 因此,从示例回到整体理论,malloc(3)在需要时从内核获取内存,通常以页面为单位。 These pages are divided or consolidated as the program requires. 这些页面根据程序要求进行划分或合并。 Malloc and free cooperate to maintain a directory. Malloc和free合作维护一个目录。 They coalesce adjacent free blocks when possible in order to be able to provide large blocks. 它们尽可能合并相邻的空闲块,以便能够提供大块。 The directory may or may not involve using the memory in freed blocks to form a linked list. 该目录可能涉及也可能不涉及在释放的块中使用内存来形成链接列表。 (The alternative is a bit more shared-memory and paging-friendly, and it involves allocating memory specifically for the directory.) Malloc and free have little if any ability to enforce access to individual blocks even when special and optional debugging code is compiled into the program. (另一种选择是共享内存和分页更友好,并且它涉及专门为目录分配内存。)即使将特殊和可选的调试代码编译到其中,Malloc和free也几乎没有能力强制访问各个块。该程序。


1. The fact that very few implementations of free() attempt to return memory to the system is not necessarily due to the implementors slacking off. 1.很少有free()的实现尝试将内存返回给系统的事实不一定是由于实现者懈怠。 Interacting with the kernel is much slower than simply executing library code, and the benefit would be small. 与内核进行交互比仅执行库代码要慢得多,并且好处很小。 Most programs have a steady-state or increasing memory footprint, so the time spent analyzing the heap looking for returnable memory would be completely wasted. 大多数程序具有稳定状态或增加的内存占用量,因此用于寻找可返回内存的分析堆所花费的时间将完全浪费。 Other reasons include the fact that internal fragmentation makes page-aligned blocks unlikely to exist, and it's likely that returning a block would fragment blocks to either side. 其他原因包括内部碎片使页面对齐的块不太可能存在的事实,并且返回一个块可能会将块碎片分散到任一侧。 Finally, the few programs that do return large amounts of memory are likely to bypass malloc() and simply allocate and free pages anyway. 最后,少数返回大量内存的程序可能会绕过malloc(),并且无论如何都只是分配和释放页面。

In theory, malloc gets memory from the operating system for this application. 从理论上讲,malloc从操作系统为此应用程序获取内存。 However, since you may only want 4 bytes, and the OS needs to work in pages (often 4k), malloc does a little more than that. 但是,由于您可能只需要4个字节,并且操作系统需要在页面中工作(通常为4k),因此malloc的作用还不止于此。 It takes a page, and puts it's own information in there so it can keep track of what you have allocated and freed from that page. 它需要一个页面,并在其中放置自己的信息,因此它可以跟踪您从该页面分配和释放的内容。

When you allocate 4 bytes, for instance, malloc gives you a pointer to 4 bytes. 例如,当您分配4个字节时,malloc会为您提供一个指向4个字节的指针。 What you may not realize is that the memory 8-12 bytes before your 4 bytes is being used by malloc to make a chain of all the memory you have allocated. 您可能没有意识到的是malloc正在使用您的4个字节之前的8-12个字节的内存来构成所有已分配内存的链。 When you call free, it takes your pointer, backs up to where it's data is, and operates on that. 当您调用free时,它将带您的指针,备份到其数据所在的位置,并对其进行操作。

When you free memory, malloc takes that memory block off the chain... and may or may not return that memory to the operating system. 当您释放内存时,malloc会将该内存块从链中移走……并且可能会也可能不会将该内存返回给操作系统。 If it does, than accessing that memory will probably fail, as the OS will take away your permissions to access that location. 如果是这样,则访问该内存可能会失败,因为操作系统将剥夺您访问该位置的权限。 If malloc keeps the memory ( because it has other things allocated in that page, or for some optimization ), then the access will happen to work. 如果malloc保留了内存(因为它在该页面中分配了其他东西,或者为了进行一些优化),则访问将起作用。 It's still wrong, but it might work. 仍然是错误的,但是可能会起作用。

DISCLAIMER: What I described is a common implementation of malloc, but by no means the only possible one. 免责声明:我所描述的是malloc的一种常见实现,但绝不是唯一可能的实现。

Your strcpy line attempts to store 9 bytes, not 8, because of the NUL terminator. 由于NUL终止符,您的strcpy行尝试存储9个字节而不是8个字节。 It invokes undefined behaviour. 它调用未定义的行为。

The call to free may or may not crash. 免费电话可能会崩溃,也可能不会崩溃。 The memory "after" the 4 bytes of your allocation might be used for something else by your C or C++ implementation. C或C ++实现可能会将分配的4个字节“之后”的内存用于其他用途。 If it is used for something else, then scribbling all over it will cause that "something else" to go wrong, but if it isn't used for anything else, then you could happen to get away with it. 如果将它用于其他用途,则对其进行乱涂乱画将导致“其他”错误,但是,如果不将其用于其他任何用途,则可能会碰巧放弃它。 "Getting away with it" might sound good, but is actually bad, since it means your code will appear to run OK, but on a future run you might not get away with it. “摆脱它”听起来不错,但实际上是不好的,因为这意味着您的代码似乎可以正常运行,但是在以后的运行中,您可能无法摆脱它。

With a debugging-style memory allocator, you might find that a special guard value has been written there, and that free checks for that value and panics if it doesn't find it. 使用调试样式的内存分配器,您可能会发现已在其中写入了特殊的保护值,并且可以免费检查该值,并在找不到该值时惊慌失措。

Otherwise, you might find that the next 5 bytes includes part of a link node belonging to some other block of memory which hasn't been allocated yet. 否则,您可能会发现接下来的5个字节包括链接节点的一部分,该链接节点属于尚未分配的其他内存块。 Freeing your block could well involved adding it to a list of available blocks, and because you've scribbled in the list node, that operation could dereference a pointer with an invalid value, causing a crash. 释放块很可能涉及将其添加到可用块列表中,并且由于您已在列表节点中进行了涂写,因此该操作可能会取消引用具有无效值的指针,从而导致崩溃。

It all depends on the memory allocator - different implementations use different mechanisms. 这完全取决于内存分配器-不同的实现使用不同的机制。

How malloc() and free() works depends on the runtime library used. malloc()和free()的工作方式取决于所使用的运行时库。 Generally, malloc() allocates a heap (a block of memory) from the operating system. 通常,malloc()从操作系统分配堆(内存块)。 Each request to malloc() then allocates a small chunk of this memory be returning a pointer to the caller. 然后,对malloc()的每个请求都会分配该内存的一小部分,以返回指向调用者的指针。 The memory allocation routines will have to store some extra information about the block of memory allocated to be able to keep track of used and free memory on the heap. 内存分配例程将必须存储有关分配的内存块的一些额外信息,以便能够跟踪堆上已使用和可用的内存。 This information is often stored in a few bytes just before the pointer returned by malloc() and it can be a linked list of memory blocks. 该信息通常存储在malloc()返回的指针之前的几个字节中,并且可以是存储块的链接列表。

By writing past the block of memory allocated by malloc() you will most likely destroy some of the book-keeping information of the next block which may be the remaining unused block of memory. 通过写出由malloc()分配的内存块,您很可能会破坏下一个块的某些簿记信息,这可能是剩余的未使用内存块。

One place where you program may also crash is when copying too many characters into the buffer. 当将太多字符复制到缓冲区中时,您编程的一个地方可能也会崩溃。 If the extra characters are located outside the heap you may get an access violation as you are trying to write to non-existing memory. 如果多余的字符位于堆之外,则在尝试写入不存在的内存时可能会遇到访问冲突。

This has nothing specifically to do with malloc and free. 这与malloc和free无关。 Your program exhibits undefined behaviour after you copy the string - it could crash at that point or at any point afterwards. 复制字符串后,您的程序表现出未定义的行为-在那时或之后的任何时候都可能崩溃。 This would be true even if you never used malloc and free, and allocated the char array on the stack or statically. 即使您从未使用过malloc和free并在堆栈上或静态分配char数组,也是如此。

malloc and free are implementation dependent. malloc和free取决于实现。 A typical implementation involves partitioning available memory into a "free list" - a linked list of available memory blocks. 典型的实现涉及将可用内存划分为“可用列表”-可用内存块的链接列表。 Many implementations artificially divide it into small vs large objects. 许多实现将其人为地分为大小对象。 Free blocks start with information about how big the memory block is and where the next one is, etc. 空闲块从有关内存块的大小以及下一个内存块的位置等信息开始。

When you malloc, a block is pulled from the free list. 当您malloc时,将从空闲列表中拉出一个块。 When you free, the block is put back in the free list. 释放时,该块将返回到释放列表中。 Chances are, when you overwrite the end of your pointer, you are writing on the header of a block in the free list. 当覆盖指针的末尾时,可能是在空闲列表中某个块的标题上进行写操作。 When you free your memory, free() tries to look at the next block and probably ends up hitting a pointer that causes a bus error. 当释放内存时,free()会尝试查看下一个块,并且可能最终会碰到导致总线错误的指针。

Well it depends on the memory allocator implementation and the OS. 好吧,这取决于内存分配器的实现和操作系统。

Under windows for example a process can ask for a page or more of RAM. 例如,在Windows下,进程可以要求页面或更多的RAM。 The OS then assigns those pages to the process. 然后,操作系统将这些页面分配给该进程。 This is not, however, memory allocated to your application. 但是,这不是分配给您的应用程序的内存。 The CRT memory allocator will mark the memory as a contiguous "available" block. CRT内存分配器会将内存标记为连续的“可用”块。 The CRT memory allocator will then run through the list of free blocks and find the smallest possible block that it can use. 然后,CRT内存分配器将遍历可用块列表,并找到它可以使用的最小块。 It will then take as much of that block as it needs and add it to an "allocated" list. 然后,它将根据需要占用尽可能多的块,并将其添加到“已分配”列表中。 Attached to the head of the actual memory allocation will be a header. 附加到实际内存分配的头部的是标头。 This header will contain various bit of information (it could, for example, contain the next and previous allocated blocks to form a linked list. It will most probably contain the size of the allocation). 该头文件将包含各种信息(例如,它可以包含下一个和上一个分配的块以形成一个链表。它很可能包含分配的大小)。

Free will then remove the header and add it back to the free memory list. Free然后将删除标题并将其重新添加到可用内存列表中。 If it forms a larger block with the surrounding free blocks these will be added together to give a larger block. 如果它与周围的空闲块形成一个更大的块,则将这些块加在一起以得到更大的块。 If a whole page is now free the allocator will, most likely, return the page to the OS. 如果现在整个页面都可用,则分配器很可能会将页面返回给OS。

It is not a simple problem. 这不是一个简单的问题。 The OS allocator portion is completely out of your control. 操作系统分配器部分完全不受您的控制。 I recommend you read through something like Doug Lea's Malloc (DLMalloc) to get an understanding of how a fairly fast allocator will work. 我建议您通读Doug Lea的Malloc(DLMalloc)之类的内容,以了解相当快速的分配器如何工作。

Edit: Your crash will be caused by the fact that by writing larger than the allocation you have overwritten the next memory header. 编辑:您的崩溃将由以下事实引起:写入大于分配的值,您已经覆盖了下一个内存头。 This way when it frees it gets very confused as to what exactly it is free'ing and how to merge into the following block. 这样,当它释放时,对于它到底是什么释放以及如何合并到下面的块中非常困惑。 This may not always cause a crash straight away on the free. 这可能并不总是会立即导致免费停车。 It may cause a crash later on. 稍后可能会导致崩溃。 In general avoid memory overwrites! 通常,避免内存覆盖!

Your program crashes because it used memory that does not belong to you. 您的程序崩溃,因为它使用了不属于您的内存。 It may be used by someone else or not - if you are lucky you crash, if not the problem may stay hidden for a long time and come back and bite you later. 它可能会被其他人使用-如果幸运的话,您将崩溃,否则,该问题可能会隐藏很长时间,然后回来再咬你。

As far as malloc/free implementation goes - entire books are devoted to the topic. 就malloc / free实现而言-整本书都致力于该主题。 Basically the allocator would get bigger chunks of memory from the OS and manage them for you. 基本上,分配器将从操作系统中获取更大的内存块,并为您管理它们。 Some of the problems an allocator must address are: 分配器必须解决的一些问题是:

  • How to get new memory 如何获得新的记忆
  • How to store it - ( list or other structure, multiple lists for memory chunks of different size, and so on ) 如何存储它-(列表或其他结构,不同大小的内存块的多个列表,依此类推)
  • What to do if the user requests more memory than currently available ( request more memory from OS, join some of the existing blocks, how to join them exactly, ... ) 如果用户请求的内存超过当前可用的内存(从OS请求更多的内存,加入一些现有的块,如何准确地加入它们,...)该怎么办?
  • What to do when the user frees memory 用户释放内存时该怎么办
  • Debug allocators may give you bigger chunk that you requested and fill it some byte pattern, when you free the memory the allocator can check if wrote outside of the block ( which is probably happening in your case) ... 调试分配器可能会为您提供您请求的更大块,并为它填充一些字节模式,当您释放内存时,分配器可以检查是否在块外写入(这可能在您的情况下发生)...

It's hard to say because the actual behaviour is different between different compilers/runtimes. 很难说,因为不同的编译器/运行时的实际行为是不同的。 Even debug/release builds have different behaviour. 甚至调试/发布版本都有不同的行为。 Debug builds of VS2005 will insert markers between allocations to detect memory corruption, so instead of a crash, it will assert in free(). VS2005的调试版本将在分配之间插入标记以检测内存损坏,因此它不会崩溃,而是在free()中声明。

It's also important to realize that simply moving the program break pointer around with brk and sbrk doesn't actually allocate the memory, it just sets up the address space. 同样重要的是要意识到,仅使用brksbrk移动程序中断指针实际上并不会分配内存,它只是设置了地址空间。 On Linux, for example, the memory will be "backed" by actual physical pages when that address range is accessed, which will result in a page fault, and will eventually lead to the kernel calling into the page allocator to get a backing page. 例如,在Linux上,访问该地址范围时,内存将由实际的物理页面“支持”,这将导致页面错误,并最终导致内核调用页面分配器以获取支持页面。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM