Pemrograman C: kesalahan SIGABRT 134; apakah saya mengosongkan memori ini dengan benar?

Saya memiliki struktur data bersarang (ini adalah inisialisasinya):

Interval *newInterval(int b, int e, int m){
    static Interval i;
    i.b = b;
    i.e = e;
    i.m = m;
    return &i;
}
Signal *newSignal(int size){
    static Signal s;
    s.intervals = malloc(size * sizeof(Interval));
    s.top = 0;
    s.size = size;
    return &s;
}

Stack *newStack(int size){
    static Stack st;
    st.signals = malloc(size * sizeof(Signal));
    st.top = 0;
    st.size = size;
    return &st;
}

Bagaimana struktur datanya: Beberapa penunjuk struktur Interval disimpan dalam larik 'interval' dari setiap struktur Signal. Setiap penunjuk struct Signal disimpan dalam array 'sinyal' dari struct Stack (hanya akan selalu ada satu).

        -> [Signal 0] -> [Interval 0][Interval 1][Interval 2]...
[Stack] -> [Signal 1] -> [Interval 0][Interval 1]
        -> [Signal 2] -> [Interval 0][Interval 1][Interval 2]...

Cara saya mencoba mengakses dan membebaskan data: Saya memiliki dua fungsi yang mencetak data dari dalam struktur, dan mencoba mengosongkan memori yang dialokasikan menggunakan malloc (dan realloc). Namun sepertinya saya mendapatkan SIGABRT (kesalahan 134). Saya kira ini karena cara saya membebaskan memori; tapi aku tidak tahu harus berbuat apa!

    void pop(Signal *s, int n){
    if(n < s->top) {
        printf("[%d,%d)@%d ", s->intervals[n].b, s->intervals[n].e, s->intervals[n].m);
        pop(s,n+1);
    }
    else {
        free(s->intervals);
    }
}

void printIntervals(Stack *st){
    for(int i=0; i<st->top; i++){
        pop(&(st->signals[i]), 0);
        printf("\n");
        free(&(st->signals[i]));
    }
}

1. printIntervals dipanggil satu kali, dan pada gilirannya memanggil fungsi pop untuk setiap sinyal.

2. Fungsi pop secara rekursif mencetak setiap struct interval, hingga array yang berisi interval kosong, pada saat itulah saya mencoba untuk membebaskan array intervals dari sinyal.

3. Pada titik ini pop selesai, dan aliran kembali ke printIntervals. Di sini, saya mencoba untuk membebaskan array sinyal karena tidak ada lagi yang tersisa untuk dicetak, dan loop bergerak untuk mencetak sinyal berikutnya dari Stack.

Apakah cara saya mengosongkan memori salah? Bagaimana cara memperbaiki kesalahan memori? Terima kasih.


person Coma    schedule 14.02.2018    source sumber
comment
static Stack st; diikuti oleh st.signals = malloc() sangat buruk, dan memori mudah bocor. Harap bersiap dan memahami arti static dalam konteks Anda menggunakannya. Tampaknya Anda ingin menghindari malloc()ing dan untuk itu Anda melakukan sesuatu yang sangat salah.   -  person Iharob Al Asimi    schedule 14.02.2018


Jawaban (1)


Jika Anda free() beberapa Stack pointer untuk mengambil satu sebagai contoh Anda benar-benar selalu membebaskan pointer yang sama.

Saat Anda mendeklarasikan struktur sebagai static dalam lingkup fungsi, struktur tersebut hanya diinisialisasi satu kali, panggilan berikutnya akan memengaruhi penunjuk yang Anda kembalikan pada awalnya dan dengan demikian menggunakan malloc() pada satu anggota secara efektif membuat semua penunjuk Anda menunjuk ke area malloc()ed yang sama. Jadi penunjuk sebelumnya yang ditunjuknya sekarang hilang dan Anda tidak dapat membebaskannya.

Selain itu, Anda tidak dapat free() sesuatu yang tidak dikembalikan oleh malloc(). Khususnya adalah mencurigakan dan mungkin salah untuk memanggil free() pada sebuah pointer yang sebenarnya merupakan hasil evaluasi alamat & operator.

Kode Anda mungkin harus diperbaiki sebagai berikut,

Interval *
newInterval(int b, int e, int m)
{
    Interval *interval;
    interval = malloc(sizeof(*interval));
    if (interval == NULL)
        return NULL;
    interval->b = b;
    interval->e = e;
    interval->m = m;
    return interval;
}

Signal *
newSignal(int size)
{
    Signal *signal;
    signal = malloc(sizeof(*signal));
    if (signal == NULL)
        return NULL;
    signal->intervals = malloc(size * sizeof(*signal->intervals));
    if (signal->intervals == NULL) {
        free(signal);
        return NULL;
    }
    signal->top = 0;
    signal->size = size;
    return signal;
}

Stack *
newStack(int size)
{
    Stack *stack;
    stack = malloc(sizeof(*stack));
    if (stack == NULL)
        return NULL;
    stack->signals = malloc(size * sizeof(*stack->signals));
    if (stack->signals == NULL) {
        free(stack);
        return NULL;
    }
    stack->top = 0;
    stack->size = size;
    return stack;
}

Selain itu, desain yang baik juga penting dan fungsi yang disebut print* tidak akan membebaskan apa pun sama sekali, bahkan Anda harus menghindari mengosongkan memori dalam konteks tertentu yang dialokasikan dalam konteks berbeda.

person Iharob Al Asimi    schedule 14.02.2018
comment
Ulang. pernyataan Khususnya secara eksplisit salah untuk memanggil free() pada pointer yang sebenarnya merupakan hasil evaluasi alamat & operator.: char *p = malloc(10); free(&p[0]); akan berfungsi dengan baik misalnya. Yang penting bukanlah alamatnya, tetapi apakah itu menghasilkan penunjuk yang benar. - person P.P; 14.02.2018