2015-04-22 65 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