我正在尝试调试一个给出错误的程序:Abort(core dumped).Valgrind检测到堆栈粉碎并给出一个LEAK SUMMARY,其中1个块仍然可以访问.它向函数downloadAndOpen的第12行发出信号,在那里我有一个我认为在main结束时关闭的fopen,但它似乎不是.我很感激这个bug的帮助.valgrind输出是:
*** stack smashing detected ***: ./mtg terminated ==9594== ==9594== HEAP SUMMARY: ==9594== in use at exit: 352 bytes in 1 blocks ==9594== total heap usage: 1 allocs, 0 frees, 352 bytes allocated ==9594== ==9594== 352 bytes in 1 blocks are still reachable in loss record 1 of 1 ==9594== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==9594== by 0x40BE62B: __fopen_internal (iofopen.c:73) ==9594== by 0x40BE70A: fopen@@GLIBC_2.1 (iofopen.c:103) ==9594== by 0x8048729: downloadAndOpen (downloadAndOpen.c:12) ==9594== by 0x80485B5: main (mtg.c:15) ==9594== ==9594== LEAK SUMMARY: ==9594== definitely lost: 0 bytes in 0 blocks ==9594== indirectly lost: 0 bytes in 0 blocks ==9594== possibly lost: 0 bytes in 0 blocks ==9594== still reachable: 352 bytes in 1 blocks ==9594== suppressed: 0 bytes in 0 blocks ==9594== ==9594== For counts of detected and suppressed errors, rerun with: -v ==9594== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) Aborted (core dumped)
编辑:修复第一个问题后,我在程序正常工作之后得到了类似的问题,直到第18页.Valgrind报告是:
==11845== Invalid read of size 4 ==11845== at 0x40C5F35: getc (getc.c:38) ==11845== by 0x80487EA: download (download.c:12) ==11845== by 0x2020201F: ??? ==11845== Address 0x420ba20 is 248 bytes inside a block of size 352 free'd ==11845== at 0x402B358: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==11845== by 0x40BDDB9: fclose@@GLIBC_2.1 (iofclose.c:85) ==11845== by 0x804866B: main (mtg.c:26) ==11845== ==11845== Invalid read of size 4 ==11845== at 0x40C5F3E: getc (getc.c:38) ==11845== by 0x80487EA: download (download.c:12) ==11845== by 0x2020201F: ??? ==11845== Address 0x420ba68 is 320 bytes inside a block of size 352 free'd ==11845== at 0x402B358: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==11845== by 0x40BDDB9: fclose@@GLIBC_2.1 (iofclose.c:85) ==11845== by 0x804866B: main (mtg.c:26) ==11845== ==11845== Invalid read of size 4 ==11845== at 0x40C5F48: getc (getc.c:38) ==11845== by 0x80487EA: download (download.c:12) ==11845== by 0x2020201F: ??? ==11845== Address 0x8 is not stack'd, malloc'd or (recently) free'd ==11845== ==11845== ==11845== Process terminating with default action of signal 11 (SIGSEGV) ==11845== Access not within mapped region at address 0x8 ==11845== at 0x40C5F48: getc (getc.c:38) ==11845== by 0x80487EA: download (download.c:12) ==11845== by 0x2020201F: ??? ==11845== If you believe this happened as a result of a stack ==11845== overflow in your program's main thread (unlikely but ==11845== possible), you can try to increase the size of the ==11845== main thread stack using the --main-stacksize= flag. ==11845== The main thread stack size used in this run was 8388608. ==11845== ==11845== HEAP SUMMARY: ==11845== in use at exit: 352 bytes in 1 blocks ==11845== total heap usage: 18 allocs, 17 frees, 6,336 bytes allocated ==11845== ==11845== 352 bytes in 1 blocks are still reachable in loss record 1 of 1 ==11845== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==11845== by 0x40BE62B: __fopen_internal (iofopen.c:73) ==11845== by 0x40BE70A: fopen@@GLIBC_2.1 (iofopen.c:103) ==11845== by 0x8048729: downloadAndOpen (downloadAndOpen.c:12) ==11845== by 0x80485B5: main (mtg.c:15) ==11845== ==11845== LEAK SUMMARY: ==11845== definitely lost: 0 bytes in 0 blocks ==11845== indirectly lost: 0 bytes in 0 blocks ==11845== possibly lost: 0 bytes in 0 blocks ==11845== still reachable: 352 bytes in 1 blocks ==11845== suppressed: 0 bytes in 0 blocks ==11845== ==11845== For counts of detected and suppressed errors, rerun with: -v ==11845== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0) Segmentation fault (core dumped)
我已经解决了问题,但我仍然看不出有什么问题:
#include#include // for using system calls #include int main (void) { char url[200], cmd[200]; int pos = 0, c, j; bool found = false; FILE *fp; fp = fopen ("file.txt", "w+"); fprintf (fp, "\"http://4.bp.blogspot.com/-mIE4JlppKMU/T9_mxKR__wI/AAAAAAAAASs/deHLBL21ZbE/s640/Temple Garden.png\""); while (!found) { if ( (c = getc (fp)) == EOF ) { printf ("Image not found\n"); return 1; } printf ("%c", c); url[pos] = c; if ( pos > 0 && url[pos-1] == 'g' && url[pos] == '\"' ) { found = true; } ++pos; } --pos; char url2[pos]; for ( j = 1; j < pos; j++ ) { url2[j - 1] = url[j]; } url2[j - 1] = '\0'; //http://joequery.me/code/snprintf-c/ // wget -q for quiet -nc, --no-clobber skip downloads that would download to existing files (no sobreescribir) snprintf(cmd, 200, "wget -q -nc -O /home/arturo/Dropbox/Digital_Renders/%d \'%s\'", 1, url2); system(cmd); return 0; }
这是主要功能的代码:
#include "helpers.h" char postBegin[] = "forum-post-body-content", postEnd[] = "p-comment-notes", img[] = "img src="; int length1 = 22, length2 = 14, length3 = 7; int pos1 = 0, pos2 = 0, pos3 = 0; int main () { bool inPost = false; FILE *fp; int c; for ( int i = 1; i <= 151; i++ ) { downloadAndOpen (&fp, i); while ( (c = getc (fp)) != EOF ) { if ( search (postBegin, length1, c, &pos1) ) inPost = true; if (inPost) { if ( search (postEnd, length2, c, &pos2) ) inPost = false; if ( search (img, length3, c, &pos3) ) download (&fp); } } fclose (fp); } }
这就是Valgrind抱怨的功能:
#include "helpers.h" void downloadAndOpen (FILE **fp, int i) { char cmd[128]={0}, file[20]; // download web page sprintf (cmd, "wget -q -O page%d.txt 'http://www.mtgsalvation.com/forums/creativity/artwork/340782-official-digital-rendering-thread?page=%d'", i, i); system (cmd); // open text file sprintf (file, "page%d.txt", i); *fp = fopen (file, "r"); }
该计划的其余部分在这里:
#include#include // for using system calls #include #include // for strlen void downloadAndOpen (FILE **fp, int i); bool search (char needle[], int length, char c, int *pos); void download (FILE* *fp); #include "helpers.h" void download (FILE **fp) { char url[128], cmd[128]; int pos = 0, c, j; static int num = 1; bool found = false; while (!found) { if ( (c = getc (*fp)) == EOF ) { printf ("Image not found\n"); return; } url[pos] = c; if ( pos > 0 && url[pos-1] == 'g' && url[pos] == '\"' ) { found = true; } ++pos; } --pos; char url2[pos]; for ( j = 1; j < pos; j++ ) { url2[j - 1] = url[j]; } url2[j - 1] = '\0'; sprintf(cmd, "wget -q -O /home/arturo/Dropbox/Digital_Renders/%d \'%s\'", num++, url2); system(cmd); } #include "helpers.h" bool search (char needle[], int length, char c, int *pos) { if (needle[*pos] == c) { if (*pos == length) { return true; *pos = -1; } (*pos)++; } else { if(*pos > 0) *pos = 0; } return false; }
和Makefile:
CC = gcc CFLAGS = -ggdb3 -O0 -std=c99 -Wall -Werror all: mtg mtg: mtg.c downloadAndOpen.c search.c download.c helpers.h $(CC) $(CFLAGS) -o mtg mtg.c downloadAndOpen.c search.c download.c clean: rm -f *.o a.out core mtg
M.M.. 6
您可能在这两个sprintf
命令中都有缓冲区溢出:
char cmd[128]={0}, file[20]; sprintf (cmd, "wget -q -O page%d.txt 'http://www.mtgsalvation.com/forums/creativity/artwork/340782-official-digital-rendering-thread?page=%d'", i, i); sprintf (file, "page%d.txt", i);
而不是尝试分析特定实例是否溢出,修复您的代码:
int n = snprintf(cmd, sizeof cmd, "............ if ( n < 0 || n >= sizeof cmd ) exit(EXIT_FAILURE); // or other error handling
和
n = snprintf(file, sizeof file, "page%d.txt", i); if ( n < 0 || n >= sizeof file ) exit(EXIT_FAILURE); // or other error handling
如果您进行此更改仍然遇到问题,请更新您的帖子.
您可能在这两个sprintf
命令中都有缓冲区溢出:
char cmd[128]={0}, file[20]; sprintf (cmd, "wget -q -O page%d.txt 'http://www.mtgsalvation.com/forums/creativity/artwork/340782-official-digital-rendering-thread?page=%d'", i, i); sprintf (file, "page%d.txt", i);
而不是尝试分析特定实例是否溢出,修复您的代码:
int n = snprintf(cmd, sizeof cmd, "............ if ( n < 0 || n >= sizeof cmd ) exit(EXIT_FAILURE); // or other error handling
和
n = snprintf(file, sizeof file, "page%d.txt", i); if ( n < 0 || n >= sizeof file ) exit(EXIT_FAILURE); // or other error handling
如果您进行此更改仍然遇到问题,请更新您的帖子.