为什么我得到不同的结果,当我取消引用释放之后的指针? [英] Why do I get different results when I dereference a pointer after freeing it?

查看:138
本文介绍了为什么我得到不同的结果,当我取消引用释放之后的指针?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个关于(在Debian GNU / Linux和GCC 4.3.3)在C内存管理的问题。

I've a question about the memory management in C (and GCC 4.3.3 under Debian GNU/Linux).

根据C编程语言预订截止K&放大器; R,(7.8.5章),当我释放一个指针,然后取消对它的引用,是错误的。但我已经有些怀疑,因为我已经指出,有时,在源,我粘贴下面,编译器(?),似乎按照一个明确的原则工作。

According to the C Programming Language Book by K&R, (chap. 7.8.5), when I free a pointer and then dereference it, is an error. But I've some doubts since I've noted that sometimes, as in the source I've pasted below, the compiler (?) seems to work according a well-defined principle.

我有一个简单的程序是这样,那就说明如何返回动态分配的数组:

I've a trivial program like this, that shows how to return an array dynamically allocated:

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


int * ret_array(int n)
{
    int * arr = (int *) malloc(10 * sizeof(int));
    int i;
    for (i = 0; i < n; i++)
    {
        arr[i] = i*2;
    }
    printf("Address pointer in ret_array: %p\n", (void *) arr);
    return arr;
}

int * ret_oth_array(int n)
{
    int * arr = (int *) malloc(10 * sizeof(int));
    int i;
    for (i = 0; i < n; i++)
    {
        arr[i] = i+n;
    }
    printf("Address pointer in ret_oth_array: %p\n", (void *) arr);
    return arr;
}

int main(void)
{
    int *p = NULL;
    int *x = NULL;
    p = ret_array(5);
    x = ret_oth_array(6);

    printf("Address contained in p: %p\nValue of *p: %d\n", (void *) p, *p);

    free(x);
    free(p);
    printf("Memory freed.\n");
    printf("*(p+4) = %d\n", *(p+4));
    printf("*x = %d\n", *x);

    return 0;
}

如果我尝试用一​​些参数来编译它: -ansi -pedantic -Wall,误差,它不会引发错误或警告。不仅;它也运行正常。

If I try to compile it with some arguments: -ansi -Wall -pedantic-errors, it doesn't raises errors or warning. Not only; it also runs fine.

Address pointer in ret_array: 0x8269008
Address pointer in ret_oth_array: 0x8269038
Address contained in p: 0x8269008
Value of *p: 0
Memory freed.
*p+4 = 8
*x = 0

*(P + 4)为8和* x为0。
为什么会这样?
如果*(P + 4)为8,不应* X是6中,由于在x数组的第一个元素是6

*(p+4) is 8 and *x is 0. Why does this happen? If *(p+4) is 8, shouldn't *x be 6, since the first element of the x-array is 6?

另一个奇怪的事情发生,如果我尝试改变调用的顺序释放。
例如:

Another strange thing happens if I try to change the order of the calls to free. E.g.:

int main(int argc, char * argv[])
{
/* ... code ... */

    free(p);
    free(x);

    printf("Memory freed.\n");
    printf("*(p+4) = %d\n", *(p+4));
    printf("*x = %d\n", *x);

    return 0;
}

在事实上在这种情况下,输出(我的机器上)将是:

In fact in this case the output (on my machine) will be:

*p+4 = 8
*x = 142106624

为什么会出现的 X 的指针真正的释放,而P指针被释放(我希望)不同?
好吧,我知道释放内存后,我应该使指针指向NULL,但我只是好奇:P

Why does the x pointer is really "freed", while the p pointer is freed (I hope) "differently"? Ok, I know that after freeing memory I should make the pointers to point to NULL, but I was just curious :P

推荐答案

免费()(和的malloc())是不是从GCC。他们来自C库,这对Debian是通常的glibc。所以,你看到的是glibc的行为,而不是gcc的(并会用不同的C库或不同版本的C库的变化)。

free() (and malloc()) are not from gcc. They come from the C library, which on Debian is usually glibc. So, what you are seeing is glibc's behavior, not gcc's (and would change with a different C library, or a different version of the C library).

我特别的,在您使用免费()你释放内存块的malloc()给你。这不是你的了。由于它不应该再使用,glibc的内部内存管理器可以自由地为所欲为的内存块,包括使用其中的一部分作为自己的内存结构(这可能是为什么你看到它的内容发生变化;他们已被覆盖与记录信息,probaly指向其他块或某种形式的计数器)。

I particular, after you use free() you are releasing the memory block malloc() gave you. It's not yours anymore. Since it is not supposed to be used anymore, the memory manager within glibc is free to do whatever it wants with the memory block, including using parts of it as its own memory structures (which is probably why you are seeing its contents change; they have been overwritten with bookkeeping information, probaly pointers to other blocks or counters of some sort).

有其他的事情可能发生;特别是,如果您分配的大小足够大,glibc的可以要求为它单独的内存块内核(与的mmap()或类似的电话),以及期间释放回内核的的免费()。在这种情况下,你的程序会崩溃。这在理论上也发生在一些circunstances甚至与小分配(glibc的可以增长/收缩堆)。

There are other things that can happen; in particular, if the size of your allocation was large enough, glibc can ask the kernel for a separate memory block for it (with mmap() or similar calls), and release it back to the kernel during the free(). In that case, your program would crash. This can in theory also happen in some circunstances even with small allocations (glibc can grow/shrink the heap).

这篇关于为什么我得到不同的结果,当我取消引用释放之后的指针?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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