【问题标题】:problem when I try add a struct to other struct and use the free function当我尝试将结构添加到其他结构并使用免费功能时出现问题
【发布时间】:2010-11-05 00:55:23
【问题描述】:

我在 C 中创建了一个名为“remover”的函数,用于删除数组“lista”的结构。此函数调整“列表”的大小。问题是我试图打印“lista”的元素,但它打印出奇怪的东西。 当我不释放“lista_aux”时,程序正常运行。为什么会这样?

typedef struct localidade{
    char nome[31];
    float local[3];
}Localidade;

Localidade** remover(Localidade** lista, char end_remover[], int posicao){
    int i, j;
    int pos_remover;
    char nome_aux[31];
    Localidade** lista_aux;
    lista_aux = (Localidade**) malloc((posicao) * sizeof(Localidade*));
    if( lista_aux == NULL){
        printf("Erro na alocacao de memoria!\n");
        exit(-1);
    }
    for( i = 0; i < posicao; i++){
        lista_aux[i] = (Localidade*) malloc(sizeof(Localidade));
        if( lista_aux[i] == NULL){
        printf("Erro na alocacao de memoria!\n");
        exit(-1);
        }
    }
    for( i = 0; end_remover[i]; i++ ){
        end_remover[i] = toupper( end_remover[i] );
    }
    for( i = 1; i < posicao; i++){
        strcpy( nome_aux, lista[i]->nome);
        for( j = 0; nome_aux[j]; j++){
            nome_aux[j] = toupper( nome_aux[j] );
        }
        if( !(strcmp( end_remover, nome_aux)) ){
            pos_remover = i;
            break;
        }
        else if( i == posicao ){
            printf("Endereco nao cadastrado.\n");
        }
    }
    for( i = 0; i < posicao; i++){
        if( i < pos_remover ){
            lista_aux[i] = lista[i];
        }
        else{
            lista_aux[i] = lista[i + 1];
        }
        //printf("***%s\n", lista_aux[i]->nome);
    }
    lista = (Localidade**) realloc( lista, (posicao)*sizeof(Localidade*));
    lista = lista_aux;
    //printf("*****%s\n", lista[1]->nome);
    /*for( i = 0; i < posicao; i++ ){
        printf("***%s\n", lista[i]->nome);
    }
    for( i = 0; i < posicao; i++ ){
        printf("*****%s\n", lista_aux[i]->nome);
    }*/
    /*for( i = 0; i < posicao; i++){
        free( lista_aux[i] );
    }
    free( lista_aux );*/

    return lista;
}

【问题讨论】:

  • 选择代码并按 CTRL+K 以正确格式化。有一个预览窗口。使用它!

标签: c struct free


【解决方案1】:

如果你释放 lista_aux,你的代码将返回一个无效的(释放的)指针给调用者,因为这行:

lista = lista_aux;

您的代码还有其他问题(取决于您如何调用它,对于初学者,您可能存在内存泄漏),我建议您检查您的算法以从“lista”中删除条目。一个建议是知道列表的大小(或以 NULL 结尾的列表),并使用 memmove() 而不是手动复制内容。

【讨论】:

    【解决方案2】:

    您的问题(嗯,其中之一)似乎在这里:

    lista = (Localidade**) realloc( lista, (posicao)*sizeof(Localidade*));
    lista = lista_aux;
    

    不会lista_aux 的所有内容复制到lista,它只是将lista 指针更改为指向lista_aux 数据(覆盖您刚刚重新分配的内存)。

    如果您随后释放该数据,则您的指针将指向已释放的内存。

    如果你创建了一个全新的数组,你不需要复制内存,你应该释放原始并返回你制作的副本:

    free (lista);
    lista = lista_aux;
    

    有一个更好的方法来做你正在尝试做的事情。这是一种更简单的形式,只需使用源索引和目标索引来删除不需要的元素。

    通常,源和目标将是相同的,因此数组不会改变,但是,当找到可移动项目时,源会递增没有目标(在为不需要的释放数据之后当然是元素)。

    我也对其进行了更改,因此它也为您提供了新尺寸。这是一个完整的程序、测试套件和所有内容:

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    typedef struct localidade {
        char nome[31];
        float local[3];
    } Localidade;
    
    static void dump ( int sz, Localidade **lista) {
        int i;
    
        printf ("Size = %d\n", sz);
        for (i = 0; i < sz; i++)
            printf ("   [%s]\n", lista[i]->nome);
    
    }
    

     

    Localidade **remover (
        Localidade **lista,
        char end_remover[],
        int posicao,
        int *new_posicao)
    {
        int sidx, didx;
    
        // Maintain separate source and destination indexes.
    
        sidx = didx = 0;
        while (sidx < posicao) {
            // If need to remove, just increment source after freeing.
    
            if (stricmp (end_remover, lista[sidx]->nome) == 0) {
                free (lista[sidx]);
                lista[sidx++] = NULL;
                continue;
            }
    
            // Otherwise transfer and increment both indexes.
    
            lista[didx++] = lista[sidx++];
        }
    
        *new_posicao = didx;
        if (sidx != didx)
            lista = realloc (lista, (*new_posicao) * sizeof(Localidade*));
        return lista;
    }
    

     

    int main (void) {
        int sz;
    
        Localidade **x = malloc (3 * sizeof(Localidade*));
        x[0] = malloc (sizeof(Localidade));
        x[1] = malloc (sizeof(Localidade));
        x[2] = malloc (sizeof(Localidade));
        sz = 3;
        strcpy (x[0]->nome, "PaxDiablo");
        strcpy (x[1]->nome, "Adriano");
        strcpy (x[2]->nome, "Kate Bush");
    
        dump (sz, x);
    
        x = remover (x, "AdRiAnO", sz, &sz);
        dump (sz, x);
    
        return 0;
    }
    

    按预期输出:

    Size = 3
       [PaxDiablo]
       [Adriano]
       [Kate Bush]
    Size = 2
       [PaxDiablo]
       [Kate Bush]
    

    【讨论】:

    • 内存泄漏和自己做事的地方有一个非常好的库函数(stricmp 用于不区分大小写的字符串比较)。
    • 非常感谢!你真的是个专家!!!不过几个月后我会比你编程好得多!(这是个笑话)。
    猜你喜欢
    • 2021-09-05
    • 2019-07-18
    • 2019-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-15
    相关资源
    最近更新 更多