微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

一旦释放结构,结构的指针仍处于活动状态?

如何解决一旦释放结构,结构的指针仍处于活动状态?

我有一个用Ubuntu编写的,用GCC编译的新C程序。 (gcc版本7.4.0(Ubuntu 7.4.0-1ubuntu1〜18.04.1))我的代码malloc()free()的结构非常多。我的程序运行了几个小时后,它崩溃并显示以下消息:

double free or corruption (fasttop)
Aborted (core dumped)

我假设“双重释放”意味着我的代码在先前free()结构上调用malloc()至少两次。那很有可能。根据我的输入,我的代码创建了许多不同的结构,尽管我有最好的意图,但它可能试图两次free()

因此,我正在与valgrind一起查找问题,但是我想到了另一种解决方案。为什么我的代码不能查看指向该结构的指针并知道该结构是否已经free()?我试图设计一个解决方案。考虑:

typedef struct MeStruct{
        int a,b,c;
}me;

me* buildMe( int a,int b,int c ){
        me* ret = malloc(sizeof(me));
        ret->a = a;     ret->b = b;     ret->c = c;
        return ret;
}

void printMe( me* me1 ){
        printf("------------------------------\n");
        printf("printMe() :: pointer address is: %p\n",me1);
        if( me1 == NULL ){
                printf("NULL\n");
        } else {
                printf( "ME struct :: %d %d %d\n",me1->a,me1->b,me1->c );
        }
        printf("------------------------------\n");
}

void freeMe( me* me1 ){
        printf("Calling freeStuff()\n");
        if( me1 != NULL ){
                free( me1 );
                me1 = NULL;      // DOES THIS DO ANYTHING???
        }
}

int main( int argc,char **argv ){

        me* me1 = buildMe( 1,2,3 );

        printMe( me1 );
        freeMe( me1 );      // First attempt to free( me1 )
        printMe( me1 );
        freeMe( me1 );      // Second attempt to free( me1 )
        printf("END OF PROGRAM.\n");
        return 1;
}

所以起初,我认为这很聪明。当free()结构被使用时,代码会将结构的指针设置为NULL,从而提供了一种方法来检测该结构是否有效。但是标有“ DOES THIS DO ANYTHIING???”的行似乎无济于事。输出如下:

------------------------------
printMe() :: pointer address is: 0x555a71097260
ME struct :: 1 2 3
------------------------------
Calling freeStuff()
------------------------------
printMe() :: pointer address is: 0x555a71097260
ME struct :: 0 0 3
------------------------------
Calling freeStuff()
END OF PROGRAM.

因此,这里对printMe()的第二次调用很有趣。此时,该结构已被free()编辑,这意味着不再分配分配给该结构的堆内存。但是,结构的指针没有改变,也许我什至可以看到一些原始数据? (me1->c仍为值“ 3”)

因此,看来我的方案无效,至少在此编译器上无效。几个问题困扰着我。首先, 为什么 不起作用?为什么在调用freeMe()之后指针的值不为NULL?又为什么第二次调用freeMe()导致程序崩溃?毕竟,第二次调用尝试第二次free()结构。

感谢任何想法或批评,谢谢。

编辑:我修复了复制/粘贴错误,该错误为“返回1;”。被放在“ printf(“程序结束。\ n”);“之前;”致电main()

解决方法

指针只是一个数字/内存地址。 free()一旦使用它,它就会保留其值,并且仍然是一个指针,尽管它不再指向有效数据。它指向的内存现在可以由内存分配器用于后续对malloc()的调用。

释放该内存后,您可能仍会从结构中看到过时的值,因为free()没有义务将释放的内存清零。但是您不应再访问它。如果您随后调用malloc()并用更多数据填充堆,则很可能会看到数据被覆盖。

正如Nate Eldredge解释的那样,C函数按值传递参数。指针未被修改的原因与以下示例中的v在调用foo()之后保持不变一样:


void foo(int a) {
    a = 3; // only modifies a in this local context
}
void bar(int *p) {
    *p = 3; // modifies what p is pointing to,i.e. v
}

int main(void) {
    int v = 1;
    foo(v);         // v is copied to foo
    assert(v == 1); // v remains untouched
    bar(&v);        // pointer to v is passed to bar
    assert(v == 3); // which is successfully modified
    return 0;
}

您传递给freeMe()的指针值与本示例中的整数值一样,不同之处在于它恰好指向某个内存地址。

请注意,双重释放会引发未定义的行为,因此,free()可以在第二次调用相同地址时做任何想要的事情---不能必须报告两次免费错误。

,

如果要为指针分配一个永久的NULL值,则需要传递指针的内存地址,而不是指针。

void freeMe1(char *temp) {
    free(temp);  // will free memory; its effect is persistent
    temp = NULL; // will assign NULL to pointer but its effect is local only
}

void freeMe2(char **temp) {
    free(*temp);  // will free memory; its effect is persistent
    *temp = NULL; // will assign NULL to pointer and its effect is persistent
}

...
int main {
    char *str = malloc(...);
    ...
    ...
    freeMe1(str);  // str is not nullified
    freeMe2(&str); // str is nullified
    ...
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。