我正在尝试调试一个给出错误的程序: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 <stdio.h>
#include <stdlib.h> // for using system calls
#include <stdbool.h>
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 <stdio.h>
#include <stdlib.h> // for using system calls
#include <stdbool.h>
#include <string.h> // 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
答案 0 :(得分: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
如果您进行此更改仍然遇到问题,请更新您的帖子。