2015-04-22 101 views
1

我想在C中寫入數據結構堆棧。我的堆棧的每個元素都是一個字符串。以下是我使用的三個文件。第一個是主要的,其他的是頭文件stack.h和文件stack.c。我將stackElement聲明爲指向元素的指針。 stackT是一個定義堆棧的結構。我試圖釋放分配內存時出現問題,因爲當我運行valgrind時,我得到Valgrind塊丟失

==31235== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) 
==31235== 
==31235== 1 errors in context 1 of 2: 
==31235== Invalid free()/delete/delete[]/realloc() 
==31235== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==31235== by 0x400893: StackDestroy (in /test) 
==31235== by 0x400B61: main (in /test) 
==31235== Address 0x51fc150 is 0 bytes inside a block of size 4 free'd 
==31235== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==31235== by 0x400B55: main (in /test) 

24 bytes in 1 blocks are definitely lost in loss record 1 of 1 

請問您能幫我嗎?

int main(){ 
stackT S; 
int r = 3, i; 
StackInit(&S, 2, r); 
printf("test\n"); 
stackElementT s0; 
s0 = malloc((r + 1) * sizeof(unsigned char)); 
memset(s0, 1, r + 1); 
s0[r] = 0; 
for (i = 0; i < r; i++) { 
    s0[i] = random() & 0xff; 
} 
StackPush(&S, s0); 
free(s0); 
StackDestroy(&S); 
return 0; 
} 

stack.h

typedef unsigned char * stackElementT; 
typedef struct { 
    stackElementT *contents; 
    int maxSize; 
    int top; 
} stackT; 

stack.c

void StackInit(stackT *stackP, int maxSize, int r) { 
stackElementT *newContents; 
int i; 
r = 3; 
newContents = malloc(sizeof(stackElementT) * maxSize); 

if (newContents == NULL) { 
     fprintf(stderr, "Insufficient memory to initialize stack.\n"); 
     exit(1); 
} 

for (i = 0; i < maxSize; i++) { 
    if ((newContents[i] = malloc(r * sizeof(stackElementT))) == NULL) { 
     fprintf(stderr, "Insufficient memory to initialize stack.\n"); 
     exit(1); 
    } 
} 

stackP->contents = newContents; 
stackP->maxSize = maxSize; 
stackP->top = -1; /* I.e., empty */ 
} 

void StackDestroy(stackT *stackP) { 
int i; 
for (i = 0; i < stackP->maxSize; i++) 
    free(stackP->contents[i]); 
free(stackP->contents); 
stackP->contents = NULL; 
stackP->maxSize = 0; 
stackP->top = -1; 
} 
void StackPush(stackT *stackP, stackElementT element) { 
if (StackIsFull(stackP)) { 
    fprintf(stderr, "Can't push element on stack: stack is full.\n"); 
    exit(1); 
} 
stackP->contents[++stackP->top] = element; 
} 

編輯:

使用下面的答案我評論免費線(S0),但我得到的下一個錯誤:

==31855== 24 bytes in 1 blocks are definitely lost in loss record 1 of 1 
==31855== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==31855== by 0x4007F9: StackInit (in /test) 
==31855== by 0x400AA9: main (in /test) 
+0

'for(i = 0; i < stackP-> maxSize; i ++)free(stackP-> contents [i]);'這會嘗試釋放空的堆棧槽。 –

+0

@ColonelThirtyTwo爲什麼他試圖釋放空棧空位? – Juan

+0

嘗試將'--track-origins = yes'標誌添加到valgrind中,如果我正確記得,它應該顯示內存分配的位置。 –

回答

1

第一個valgrind消息非常清晰:您將同一塊內存釋放兩次,首先在main中使用free(s0),在StackDestroy中第二次釋放。 Chang你的代碼,所以它不會這樣做 - 要麼讓堆棧獲得對象的所有權(這樣它就可以釋放它們,而main則不會),反之亦然(堆棧不擁有對象的所有權,並且不釋放他們)。

「塊丟失」的問題是因爲您爲StackInitStackPush中的每個堆棧槽中的每個堆棧槽分配了內存塊,覆蓋了指針,因此您永遠不會釋放爲已用堆棧槽分配的原始內存。此處至少有兩種可能的解決方案:不要在StackInit(僅複製StackPush中的指針)中預先分配內存塊,要麼在StackPush中複製元素數據(而不是指針)。

+1

當我評論「free(s0);」現在我只有一個錯誤,但錯誤。錯誤是1個塊中的24個字節肯定是丟失了1個丟失記錄1 – Juan

+0

oks我選擇了第二個選項,然後我改變了stackP-> contents [++ stackP-> top] = element;通過memcpy(stackP-> contents [++ stackP-> top],element,r);但是我得到4個字節在1個塊中肯定丟失了1個丟失記錄1 == 32064 ==在0x4C2AB80:malloc(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) == 32064 == by 0x400B70:main(in/test) – Juan

+1

由於您已經更改'StackPush'來複制數據(而不是取得指針的所有權),所以您需要再次在'main'中釋放malloced's0'塊。 –

0

你可以免費s0 StackDestroy()main()

+1

當我評論「free(s0);」現在我只有一個錯誤,但錯誤。錯誤是1個塊中的24個字節絕對丟失在1的損失記錄1中。 – Juan