当我尝试将结构添加到其他结构并使用自由函数时出现问题

时间:2010-11-05 00:55:24

标签: c struct free

我在C中创建了一个名为'remover'的函数,用于删除数组'lista'的结构。此功能调整'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;
}

2 个答案:

答案 0 :(得分:1)

你的问题(好吧,其中一个)似乎在这里:

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

复制lista_auxlista的所有内容,它只是将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]

答案 1 :(得分:1)

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

lista = lista_aux;

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