如何用C*和malloc的工作?

问题描述:

我试图弄清楚发生了什么事想如果我尝试从中间释放的指针
例如,看看下面code:

I'm trying to figure out what would happened if I try to free a pointer "from the middle" for example, look at the following code:

char *ptr = (char*)malloc(10*sizeof(char));

for (char i=0 ; i<10 ; ++i)
{
	ptr[i] = i+10;
}
++ptr;
++ptr;
++ptr;
++ptr;
free(ptr);

我得到一个未处理的异常错误味精崩溃。
我想知道为什么和*是如何工作的,让我不仅知道如何使用它,但也能理解奇怪的错误和异常,更好地调试我的codeץ

I get a crash with an Unhandled exception error msg. I want to understand why and how free works so that I know not only how to use it but also be able to understand weird errors and exceptions and better debug my codeץ

非常感谢

当您的malloc块,它实际上分配更多的内存比你自找的。这种额外的存储器用于存储信息,例如所分配的块的大小,并且在块的链到下一个空闲/用块的链接,以及有时有的保护数据,可为系统如果写过去检测您的分配块的结尾。此外,大多数分配器将四舍五入的总尺寸和/或存储器的一部分的以字节的倍数(例如,一个64位的系统上它可能对齐数据以64位(8字节),为多个启动来自非对齐的地址访问数据可以是更加困难和低效率为处理器/总线),因此也可与一些填充(未使用字节)结束。

When you malloc a block, it actually allocates a bit more memory than you asked for. This extra memory is used to store information such as the size of the allocated block, and a link to the next free/used block in a chain of blocks, and sometimes some "guard data" that helps the system to detect if you write past the end of your allocated block. Also, most allocators will round up the total size and/or the start of your part of the memory to a multiple of bytes (e.g. on a 64-bit system it may align the data to a multiple of 64 bits (8 bytes) as accessing data from non-aligned addresses can be more difficult and inefficient for the processor/bus), so you may also end up with some "padding" (unused bytes).

当你释放你的指针,它使用该地址找到它添加到您的分配块的开头(通常)的特殊信息。如果在不同的地址传递,将访问包含垃圾存储器,因此其行为是未定义的(但最经常会导致崩溃)

When you free your pointer, it uses that address to find the special information it added to the beginning (usually) of your allocated block. If you pass in a different address, it will access memory that contains garbage, and hence its behaviour is undefined (but most frequently will result in a crash)

之后,如果免费()块,但没有忘记您的指针,你可能会意外地通过,在未来的指针试图访问数据,而行为是不确定的。凡有下列情况可能发生:

Later, if you free() the block but don't "forget" your pointer, you may accidentally try to access data through that pointer in the future, and the behaviour is undefined. Any of the following situations might occur:


  • 内存可能会被放在空闲块的列表,所以当你访问它,它仍然发生包含你离开那里的数据,和你的code运行正常。

  • 内存分配器可以给(的一部分)的内存,你的程序的其他部分,这将presumably已被盖写(部分)的旧数据,所以当你读它,你会得到垃圾这可能会导致从code意外的行为或崩溃。或者,你将覆盖其他数据,导致你的程序在未来的某个时刻表现出奇的另一部分。

  • 内存可能已返回给操作系统(即页面的记忆,你是不再使用可以从您的地址空间中删除,因此不再在该地址可用任何内存 - 基本上是一个未使用在你的应用程序的内存洞)。当应用程序试图访问数据就会产生硬内存故障并杀死你的进程。

这就是为什么要确保你释放它指向的内存后不要用一个指针是很重要的 - 我们的最佳做法是释放内存后,设置指针NULL,因为你可以很容易地测试NULL,并试图通过NULL指针访问内存会导致糟糕,但相一致的行为,这是更易于调试。

This is why it is important to make sure you don't use a pointer after freeing the memory it points at - the best practice for this is to set the pointer to NULL after freeing the memory, because you can easily test for NULL, and attempting to access memory via a NULL pointer will cause a bad but consistent behaviour, which is much easier to debug.