我在以下C程序中修复了三个错误。前两个给出并保证是正确的。第三个是我将在最后写的一个,与我的问题无关。最后三个问题出在哪里,每个都出现错误。
这是我的计划:
/* is correct*/
Node *create_list(int arr[], int size) {
Node *n, *list= NULL;
if (arr != NULL && size != 0)
while (size-- > 0) {
n= malloc(sizeof(*n));
if (n == NULL)
return NULL; /* we just return NULL if memory allocation fails */
else {
n->value= arr[size];
n->next= list;
list= n;
}
}
return list;
}
/* is correct*/
void list_to_string(Node *list, char result[]) {
char temp[MAX_LEN + 1];
strcpy(result, ""); /* clear out any existing contents */
while (list != NULL) {
sprintf(temp, "%d", list->value);
if (strlen(result) + strlen(temp) + 1 < MAX_LEN) {
strcat(result, temp);
/* add a space if it's not the last element */
if (list->next != NULL)
strcat(result, " ");
}
list= list->next;
}
}
/*****************************************************************************/
/* functions below this have something wrong with them */
/*****************************************************************************/
/* this function's parameter is a pointer to the head node of a list; it
* should release all of the memory of the list, and set the head pointer
* (meaning the pointer that its parameter points to) to NULL. (Empty for now).
*/
void clear(Node **list) {
}
/* should return the sum of the values in the even-numbered positions of a
* list (the value in the second node, the fourth node, etc.), but has a bug
* (the first node is considered to be position #1, in other words, the list
* has no position zero)
*/
int sum_even(Node *list) {
Node *ptr= list->next;
int sum= 0;
if (list != NULL){
while (ptr != NULL) {
sum += ptr->value;
ptr= ptr->next->next;
}
}
return sum;
}
/* should remove the last element from a list, returning 1 upon success or 0
* if start is NULL, but has a bug
*/
int remove_last(Node **start) {
Node *prev= NULL, *travel;
int result= 0;
if (start != NULL) {
result= 1;
travel= *start;
while (travel != NULL && travel->next != NULL) {
prev= travel;
travel= travel->next;
}
if (prev != NULL) {
free(prev->next);
prev->next= NULL;
}
}
return result;
}
/* should remove the first element from a list, returning 1 upon success or
* 0 if the list is empty or start is NULL, but has a bug
*/
int remove_first(Node **start) {
Node **temp= NULL;
int result= 0;
if (start != NULL && *start != NULL) {
result= 1;
temp= start;
*start= (*start)->next;
free(temp);
}
return result;
}
我的主要测试功能:
int main(void) {
int arr[]= {10, 20, 30, 40, 50, 60, 70};
Node *list= NULL;
char elements[MAX_LEN + 1];
list= create_list(arr, sizeof(arr) / sizeof(arr[0]));
/* test sum_even() */
assert(sum_even(list) == 120);
/* test remove_last() */
remove_last(&list);
list_to_string(list, elements);
assert(strcmp(elements, "10 20 30 40 50 60") == 0);
printf("Score!\n"); /* both assertions passed */
/* if your clear() function works, this program should not have any memory
leaks, and list should be NULL afterwards */
clear(&list);
return 0;
}
我理解&#39; clear()&#39;是空的,但这是我将在最后写的一个函数。当我用valgrind运行时,我感到困惑的是:
valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --track-fds=yes my_program.x
我收到此消息:
==25457== Memcheck, a memory error detector
==25457== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==25457== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==25457== Command: public1.x
==25457==
Score!
==25457==
==25457== FILE DESCRIPTORS: 3 open at exit.
==25457== Open file descriptor 2: /dev/pts/11
==25457== <inherited from parent>
==25457==
==25457== Open file descriptor 1: /dev/pts/11
==25457== <inherited from parent>
==25457==
==25457== Open file descriptor 0: /dev/pts/11
==25457== <inherited from parent>
==25457==
==25457==
==25457== HEAP SUMMARY:
==25457== in use at exit: 96 bytes in 6 blocks
==25457== total heap usage: 7 allocs, 1 frees, 112 bytes allocated
==25457==
==25457== 80 bytes in 5 blocks are indirectly lost in loss record 1 of 2
==25457== at 0x4C28A2E: malloc (vg_replace_malloc.c:270)
==25457== by 0x40077F: create_list (broken-lists.c:16)
==25457== by 0x400698: main (public1.c:14)
==25457==
==25457== 96 (16 direct, 80 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==25457== at 0x4C28A2E: malloc (vg_replace_malloc.c:270)
==25457== by 0x40077F: create_list (broken-lists.c:16)
==25457== by 0x400698: main (public1.c:14)
==25457==
==25457== LEAK SUMMARY:
==25457== definitely lost: 16 bytes in 1 blocks
==25457== indirectly lost: 80 bytes in 5 blocks
==25457== possibly lost: 0 bytes in 0 blocks
==25457== still reachable: 0 bytes in 0 blocks
==25457== suppressed: 0 bytes in 0 blocks
==25457==
==25457== For counts of detected and suppressed errors, rerun with: -v
==25457== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6)
这清楚地表明对create_list()的函数调用存在问题。既然我知道create_list()是正确的并且remove_last()有问题,为什么它告诉我create_list()有问题?
我现在正试图学习Valgrind所以请原谅我这个问题对你们有些人是否明显。
答案 0 :(得分:0)
create_list
在循环内调用malloc
。如果循环中的malloc
在前N次正常但是在N + 1时间内失败,则返回NULL
,从而从前N个malloc泄漏内存。所以这显然是create_list
中的一个错误,我希望valgrind
报告错误。
您需要以下内容:
if (n == NULL)
{
clear(&list);
return NULL; /* we just return NULL if memory allocation fails */
}
除此之外,我不确定在实施valgrind
功能之前运行clear
是否有意义。 valgrind
应该如何知道你打算在尚未编写的函数中释放内存?
答案 1 :(得分:0)
我发现了问题所在。 事实证明,clear()需要在main存在之前被调用,或者list将包含不同的内存。 由于这三个功能存在缺陷,我一开始并不认为这是个案。 sum_even()和remove_last()中的错误不适用于main()中的特定列表。所以对于这次运行,没有错。