为什么免费崩溃时调用两次 [英] Why free crashes when called twice

查看:118
本文介绍了为什么免费崩溃时调用两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C和C ++,免费(my_pointer)崩溃时,它被称为两次。

In C and C++, free(my_pointer) crashes when it is called twice.

为什么呢?种种的malloc 的记账与大小一起。当第一个免费叫,那么它标识,这是什么尺寸,这就是为什么我们需要的不是用免费电话传递下去的大小进行分配。

Why? There is bookkeeping of every malloc along with the size. When the first free is called then it identifies that this was allocated with what size that's why we need not to pass size along with free call.

既然知道每一件事情为什么没有周围检查第二个时间,什么也不做?

Since it knows every thing why doesn't it check the second time around and do nothing?

要么我不明白的malloc /免费行为或免费是不是安全实施。

Either I don't understand malloc/free behavior or free is not safely implemented.

推荐答案

您不准叫免费上未分配的内存中,标准规定相当清楚(略转述,我的重点):

You are not allowed to call free on unallocated memory, the standard states that quite clearly (slightly paraphrased, my emphasis):

免费功能使空间指向它的参数被释放,也就是进一步的分配可用。如果参数为空指针,​​不会发生任何操作。否则,如果该参数不匹配,内存管理功能早些时候返回一个指针,或者如果空间已被释放呼叫释放或realloc,行为的不确定的。

The free function causes the space pointed to by its argument to be deallocated, that is, made available for further allocation. If the argument is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

会发生什么情况,例如,如果地址你是双释放已在新块分配它的code的中间被重新分配正好存放有东西,看起来像一个真正的malloc-块头?这样的:

What happens, for example, if the address you're double-freeing has been reallocated in the middle of a new block and the code that allocated it just happened to store something there that looked like a real malloc-block header? Like:

 +- New pointer    +- Old pointer
 v                 v
+------------------------------------+
|                  <Dodgy bit>       |
+------------------------------------+

混乱,那是什么。

Chaos, that's what.

内存分配函数就像电锯工具,并提供正确使用它们,你应该没有问题。如果滥用它们,但是,其后果是你自己的错,要么破坏内存或更差,或切断你的武器之一: - )

Memory allocation functions are a tool just like a chainsaw and, provided you use them correctly, you should have no problems. If you misuse them, however, the consequences are your own fault, either corrupting memory or worse, or cutting off one of your arms :-)

和有关评论:

...它可以优雅地传达给最终用户对免费翻倍相同的位置。

... it can communicate gracefully to enduser about the doubling free the same location.

将所有的malloc 免费的记录的短促的叫声,以确保您做免费的双不块,我不认为这是可行的。这需要巨大的开销和的还是的不会解决所有问题。

Short of keeping a record of all malloc and free calls to ensure you don't double-free a block, I can't see this as being workable. It would require a huge overhead and still wouldn't fix all the problems.

会发生什么,如果:


  • 线程A分配和释放内存地址42。

  • 线程B分配的内存地址,一个42和开始使用它。

  • 线程A释放的内存进行第二次。

  • 线程C-分配内存地址42和开始使用它。

您然后让线程B和C都认为他们自己的内存(这些并不一定要执行的线程,我使用的术语线程这里只是一个棋子code的运行 - 它可以所有在执行,但所谓的顺序)的一个线程。

You then have threads B and C both thinking they own that memory (these don't have to be threads of execution, I'm using the term thread here as just a piece of code that runs - it could all be in the one thread of execution but called sequentially).

没有,我认为目前的的malloc 免费也蛮好只要你正确地使用它们。通过一切手段想一想,实现自己的版本,我认为没有错的,但我怀疑你会碰到一些pretty棘手的性能问题。

No, I think the current malloc and free are just fine provided you use them properly. By all means give some thought to implementing your own version, I see nothing wrong with that but I suspect you'll run into some pretty thorny performance issues.

如果您的的要实现绕免费您自己的包装,你可以把它更安全(在一点点的性能损失为代价) ,特别是与类似的 myFreeXxx 以下要求:

If you do want to implement your own wrapper around free, you can make it safer (at the cost of a little performance hit), specifically with something like the myFreeXxx calls below:

#include <stdio.h>
#include <stdlib.h>

void myFreeVoid (void **p) { free (*p); *p = NULL; }
void myFreeInt  (int  **p) { free (*p); *p = NULL; }
void myFreeChar (char **p) { free (*p); *p = NULL; }

int main (void) {
    char *x = malloc (1000);
    printf ("Before: %p\n", x);
    myFreeChar (&x);
    printf ("After:  %p\n", x);
    return 0;
}

在code的结果是,你可以叫 myFreeXxx 的指针指针,它会都:


  • 释放内存;和

  • 指针设置为NULL。

这后一点意味着,如果你尝试再次释放指针,它不会做任何事情(因为释放NULL是由专门的标准所覆盖)。

That latter bit means that, if you try to free the pointer again, it will do nothing (because freeing NULL is specifically covered by the standard).

它的不会的保护你的所有情况,例如,如果你使指针的拷贝其他地方,释放原始的,就可以自由复制:

It won't protect you from all situations, such as if you make a copy of the pointer elsewhere, free the original, then free the copy:

char *newptr = oldptr;
myFreeChar (&oldptr);     // frees and sets to NULL.
myFreeChar (&newptr);     // double-free because it wasn't set to NULL.


如果你到使用C11,还有比有显式调用不同的函数为每种类型的,现在C的编译时间函数重载一个更好的办法。您可以使用通用的选择,以调用正确的函数,同时仍然允许类型安全:


If you're up to using C11, there's a better way than having to explicitly call a different function for each type now that C has compile time function overloading. You can use generic selections to call the correct function while still allowing for type safety:

#include <stdio.h>
#include <stdlib.h>

void myFreeVoid (void **p) { free (*p); *p = NULL; }
void myFreeInt  (int  **p) { free (*p); *p = NULL; }
void myFreeChar (char **p) { free (*p); *p = NULL; }
#define myFree(x) _Generic((x), \
    int** :  myFreeInt,  \
    char**:  myFreeChar, \
    default: myFreeVoid  )(x)

int main (void) {
    char *x = malloc (1000);
    printf ("Before: %p\n", x);
    myFree (&x);
    printf ("After:  %p\n", x);
    return 0;
}

通过这一点,你只需拨打 myFree ,它会根据类型选择正确的功能。

With that, you simply call myFree and it will select the correct function based on the type.

这篇关于为什么免费崩溃时调用两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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