C语言中的free无法正常工作的问题

9nvpjoqh  于 2023-01-25  发布在  其他
关注(0)|答案(3)|浏览(465)

我写了这个程序,我想释放一个结构myStruct,但它没有编译,它说:
free():在tcache2中检测到双释放
你能帮帮我吗?

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

typedef struct myStruct {
    char* chaine;
    struct myStruct* next;
} mystruct;

void supprimer(myStruct* D) {
    free(D->chaine);
    free(D);
}

int main()
{
    myStruct* D = malloc(sizeof(myStruct));
    D->next = NULL;
    char* chaine = malloc(sizeof(char)*10);
    chaine = "ouii";
    D->chaine = chaine;
    supprimer(D);
    printf("Hello World");

    return 0;
}

我试着创建一个新的结构并删除它,但它不工作。

0md85ypi

0md85ypi1#

chaine = "ouii";是错误的。它没有将“ouii”复制到chaine所指向的内存中,而是将指针chaine设置为指向为字符串字面值"ouii"创建的数组。该地址不应传递给free
chaine = "ouii";更改为strcpy(chaine, "ouii");

pw136qt2

pw136qt22#

char* chaine = malloc(sizeof(char)*10);
    chaine = "ouii";

第二条语句更改chaine最初指向的内容(即malloc返回的堆内存区域的指针),这样它现在就指向字符串常量ouii。(已泄漏内存),并正在尝试free内存分配函数之一未返回的内存。因此出现警告。
可能的修复方法:

  • 使用标准strcpy复制字符串。
strcpy (chaine, "ouii");

并将#include <string.h>添加到头列表中。
附带说明:malloc在失败时返回NULL。在访问指针之前应该检查它是否有效。在POSIX兼容系统上,它还将errno设置为ENOMEM。下面是我在main ()中更喜欢的一种处理方法:

#include <errno.h>

errno = 0;
char *chaine = malloc (10); /* sizeof (char) is defined to be 1 */

if (!chaine) {
    errno = ENOMEM;
    perror ("malloc");
    return EXIT_FAILURE;
}

另请参阅:How do I modify a char** in another function

kqlmhetl

kqlmhetl3#

此代码片段

char* chaine = malloc(sizeof(char)*10);
chaine = "ouii";

导致内存泄漏。
首先动态分配内存,并将其地址分配给指针chaine

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

然后用字符串文字"ouii"的第一个字符的地址重新分配指针

chaine = "ouii";

所以动态分配内存的地址丢失了。
代替这个任务

chaine = "ouii";

需要使用在头文件<string.h>中声明的标准字符串函数strcpy将字符串常量的字符复制到动态分配的内存中。

#include <string.h>

//...

char* chaine = malloc(sizeof(char)*10);
strcpy( chaine, "ouii" );

注意这个功能

void supprimer(myStruct* D) {
    free(D->chaine);
    free(D);
}

使指针D在main中声明

myStruct* D = malloc(sizeof(myStruct));

无效。
最好通过引用将指针传递给函数。
在C语言中,通过引用传递意味着通过指向对象的指针间接传递对象(包括指针)。因此,对指针解引用后,您将可以直接访问指针所指向的对象,并可以更改它。
同样,如果你想定义一个单链表,那么这个函数可以看起来像下面这样

void supprimer( myStruct **D ) 
{
    while ( *D != NULL )
    {
        myStruct *current = *D;
        *D = ( *D )->next;
        free( current->chaine );
        free( current );
    }
}

函数的调用方式如下

supprimer( &D );

在这种情况下,调用函数后,main中定义的指针D将等于NULL
请注意,您应该检查内存分配是否成功,以避免未定义的行为。
下面是一个演示程序,展示了如何实现您的列表。

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

typedef struct myStruct
{
    char *chaine;
    struct myStruct *next;
} mystruct;

int push ( myStruct **D, const char *chaine )
{
    myStruct *current = malloc( sizeof( *current ) );
    int success = current != NULL;

    if (success)
    {
        current->chaine = malloc( strlen( chaine ) + 1 );
        success = current->chaine != NULL;

        if (success)
        {
            strcpy( current->chaine, chaine );
            current->next = *D;
            *D = current;
        }
        else
        {
            free( current );
        }
    }

    return success;
}

void supprimer( myStruct **D )
{
    while (*D != NULL)
    {
        myStruct *current = *D;
        *D = ( *D )->next;
        free( current->chaine );
        free( current );
    }
}

void output( const myStruct *D )
{
    for ( const myStruct *current = D; current != NULL; current = current->next )
    {
        printf( "\"%s\" -> ", current->chaine );
    }

    puts( "null" );
}

int main( void )
{
    myStruct *D = NULL;

    push( &D, "World" );
    push( &D, "Hello" );

    output( D );

    supprimer( &D );
}

程序输出为

"Hello" -> "Word" -> null

相关问题