簡體   English   中英

釋放用C實現的堆棧

[英]Free the stack implemented in C

我用C語言實現了堆棧及其功能。現在,在調用所有功能之后,我想釋放堆棧。

我的問題是我應該先釋放堆棧“ st”的基指針還是直接釋放堆棧“ st”? 兩者似乎都在我的代碼中工作。

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

#define init_size 10
#define increment 1

typedef struct sqStack
{
    int* top;
    int* base;
    int stack_size;
}sqStack;

int init_stack(sqStack* sq)
{
    if(sq->base==NULL)
    {
       sq->base = (int*)malloc(init_size*sizeof(int));
    }
    if(sq->base==NULL) exit(-1);
    sq->stack_size=init_size;
    sq->top=sq->base;
    return 1;
}
int push(sqStack* sq, int e)
{
    if(sq==NULL) exit(-1);

    if(sq->top-sq->base==sq->stack_size-1)//pointer top reaches the top of the stack
    {
        int* q = (int*)realloc(sq->base,(sq->stack_size+increment)*sizeof(int));
        if(q==NULL)  exit(-1);
            sq->base=q;
        sq->top=sq->base+sq->stack_size-1;
            sq->stack_size += increment;

    }
    *sq->top++=e;
    return 1;
}
int pop(sqStack* sq,int* e)
{
    if(sq==NULL) exit(-1);
    if(sq->base==sq->top)  exit(-1);
    sq->top--;
    *e=*sq->top;
    sq->stack_size--;
    return *e;
}
int top(sqStack* sq,int* e)
{
    if(sq==NULL) exit(-1);
    if(sq->base==sq->top)  exit(-1);
    *e=*(sq->top-1);
    return *e;
}
int empty(sqStack* sq)
{
    if(sq->base==sq->top) return 1;
    else return 0;
}

int main() {
    sqStack* st= (sqStack*)calloc(1,sizeof(sqStack))  ;
    int e;
    init_stack(st);
    for(int i=0;i<12;i++)
    {
        push(st,i+1);

    }
    for(int i=0;i<12;i++)
    {
        printf("%d\n",top(st,&e));
        printf("%d\n",pop(st,&e));
    }
    free(st->base);
    free(st);
    return 0;
}

結果是:12 12 11 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1每個數字都位於一行上。

mallocfree而言,您所擁有的是正確的。

您只應free mallocrealloc返回的內容。 您為結構和堆棧分配空間,然后釋放兩者,因此不會泄漏任何內存。

您不希望先free(st)因為這樣做之后, st指向的內存不再有效,並且您隨后無法安全地free(st->base) 同樣,由於free對給定內存的內容一無所知,因此它不會嘗試釋放該內存可能包含的任何指針。 因此,僅調用free(st)泄漏st->base的內存。

每個分配都應與相應的free配對,因此在您的情況下,這意味着要同時釋放st->basest 但是您的程序僅在終止之前立即執行釋放,如果程序終止,則它免費釋放的所有內容都會被OS收回。 諸如Valgrind之類的內存使用分析器可以為您檢測出差異,但實際上並不重要。

您的代碼是正確的。 相反的順序可能會起作用,但是如果確實如此,那將是偶然的。

原因是free(st)取消分配了存儲對象*st的內存。 指針st->base被存儲在此內存的一部分中。 假設某個其他任務或線程在釋放后立即獲取了相同的內存。 然后怎樣呢? 也就是說,最終調用free(st->base)會發生什么?

答:會發生什么是不確定的。

即使仍然可以從st->base檢索地址(並且不可能),該地址也可能已被任意數據覆蓋,在這種情況下, free(st->base)將任意數據解釋為一個地址將要求操作系統解除分配......好吧,你不知道它會要求操作系統解除分配。 在這種情況下,人們幾乎不能指望取得好的結果。

你做得很好。 您的排序是正確的。

其他注意事項

為了安全起見,現代操作系統內核有時會自動用空或隨機數據覆蓋釋放的內存。 同樣,他們有時會撤消程序對已通過(虛擬)方式釋放內存的硬件頁面的訪問,或者收緊允許訪問的范圍。 其中一些比其他可能性更大,但我已經看到這三個中至少有兩個發生了。 關鍵在於,根據內核最新的內存管理和安全算法,內核可以自由選擇立即,早,晚或根本不執行這些操作,因為內核不希望您的程序在乎釋放的內容程序重新分配后的內存。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM