bytes lost after freeing getline() buffer
我到处寻找有关使用getline()时valgrind内存泄漏的帖子。
本质上,我的代码所做的是使用getline()在一行中读取的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | int main(){ LL A; LLinit(&A); size_t len = 5; char *lineOrigin = (char *)malloc(len); char *line_ptr = lineOrigin; getline(&line_ptr,&len,stdin); int status, val; while( (status = sscanf(line_ptr,"%d",&val) ) >= 0){ printf("%d ",status); //if(isBadInput(line_ptr)){...} if(status == 0){ printf("ENCOUNTERED BAD INPUT. STOPPING "); return 1; } Node *node_ptr = (Node *)malloc(sizeof(Node)); node_ptr->val = val; append(&A,node_ptr); line_ptr = lookPastSpace(line_ptr); } printLL(&A); freeLL(&A); free(lineOrigin); return 0; |
}
如您所见,我为char * lineOrigin分配了一些内存,然后有第二个指针* line_ptr,它指向* lineOrigin,在以后的代码中进行了突变。
此代码块几乎从stdin读取整数并将它们按顺序存储到LinkedList中。
每次sscanf将int读入&val时,我都会使用lookPastSpace()在字符串中的非空格字符上移动* line_ptr,直到遇到另一个空格为止,然后再将指针移动一个缺口,以便line_ptr现在指向字符串中可以读取新int的下一个位置
1 2 3 4 5 6 7 | line_ptr ="123 456 789 " line_ptr = lookPastSpace(line_ptr) line_ptr ="456 789 " ... line_ptr ="" -->sscanf stops. |
事后,我走下链表,释放了每个分配的节点,并且由于节点没有分配内存的内容,所以我不得不释放LL的内存。
然后,稍后,我释放char * lineOrigin,这大概应该可以工作,因为它是最初分配的缓冲区,但是没有。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | tylerjgabb@lectura:~/HW6/medianDir$ make mem valgrind median ==11827== Memcheck, a memory error detector ==11827== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==11827== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info ==11827== Command: median ==11827== 123 456 789 1 1 1 [123, 456, 789] ==11827== Invalid free() / delete / delete[] / realloc() ==11827== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==11827== by 0x400B37: main (in /p3/ht/tylerjgabb/HW6/medianDir/median) ==11827== Address 0x51ff040 is 0 bytes inside a block of size 5 free'd ==11827== at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==11827== by 0x4EA5F9A: getdelim (iogetdelim.c:106) ==11827== by 0x400A73: main (in /p3/ht/tylerjgabb/HW6/medianDir/median) ==11827== ==11827== ==11827== HEAP SUMMARY: ==11827== in use at exit: 13 bytes in 1 blocks ==11827== total heap usage: 5 allocs, 5 frees, 66 bytes allocated ==11827== ==11827== LEAK SUMMARY: ==11827== definitely lost: 13 bytes in 1 blocks ==11827== indirectly lost: 0 bytes in 0 blocks ==11827== possibly lost: 0 bytes in 0 blocks ==11827== still reachable: 0 bytes in 0 blocks ==11827== suppressed: 0 bytes in 0 blocks ==11827== Rerun with --leak-check=full to see details of leaked memory ==11827== ==11827== For counts of detected and suppressed errors, rerun with: -v ==11827== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) tylerjgabb@lectura:~/HW6/medianDir$ |
我有点卡住了,很困惑。有什么想法吗?
-------------- TYPEDEFS和LL函数的说明-----------------
LLfuncs.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include"LinkedListHeader.h" #include <stdlib.h> void LLinit(LL *LL_ptr){ LL_ptr->head_ptr = NULL; LL_ptr->tail_ptr = NULL; LL_ptr->length = 0; } void freeLL(LL *LL_ptr){ Node *curr_ptr = LL_ptr->head_ptr; while(curr_ptr != NULL){ Node *next_ptr = curr_ptr->next_ptr; free(curr_ptr); curr_ptr = next_ptr; } } |
以上只是我的LLfuncs.c的一小部分
LinkedListHeader.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /* This is a header file containing typedefs and macros for linked lists *Tyler J Gabb *For assignment 6a. Shuffle. */ #include <stdio.h> #define showLocs(LL) printf("head_ptr = %p, tail_ptr = %p length = %d ",LL.head_ptr,LL.tail_ptr,LL.length) typedef struct LinkedListNode { int val; struct LinkedListNode *next_ptr; } Node; typedef struct LinkedList { Node *head_ptr; Node *tail_ptr; int length; } LL; |
LLinit()初始化任何最近声明的LL类型,使其头和尾为0x0,长度为0。这有助于使LL发生变化的其他函数
---------------------------一些其他有趣的信息-----------------
如果输入字符串的大小小于len的原始值,那么我不会出现内存泄漏(有时)
您基本上具有以下模式:
1 2 3 4 5 6 | char *lineOrigin, *line_ptr; size_t len = 5; lineOrigin = malloc(len); line_ptr = lineOrigin; getline(&line_ptr, &len, stdin); |
因为
本质上,您将在
编写模式的正确方法很简单。首先将行指针定义为
1 2 3 | char *line_ptr = NULL; size_t line_max = 0; ssize_t line_len; |
您使用读取了一行或多行
1 2 3 4 5 6 7 8 9 10 11 |
您可以根据需要多次重复上述操作,但是您需要意识到
完成后,释放行缓冲区。因为
1 2 3 |
现在,清除变量并不是绝对必要的,但是我发现这是一个好习惯,有时甚至可以帮助调试。
另请注意,即使在