valgrind给出错误但无法找到位置

时间:2011-10-05 01:31:56

标签: c memory-leaks makefile valgrind dlopen

我已经开始在前一天使用valgrind按照SO本身的人的建议。它是一个了不起的工具,但今天我遇到了一个问题。它给出了以下错误:definitely lost bytes但无法告诉错误的位置。

以下是valgrind的输出:

 udit@udit-Dabba ~ $  valgrind --leak-check=full  sendip -v -p ipv6 
 -f file.txt -6s ::1 -p ah -as 0x20 -aq 0x40 -ak "yugal" -am xorauth.so
 -p udp -us 21 -  ud 21 ::2 

 ==12885== Memcheck, a memory error detector
 ==12885== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
 ==12885== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
 ==12885== Command: sendip -v -p ipv6 -f file.txt -6s ::1 -p ah 
 -as 0x20 -aq 0x40 -ak "yugal" -am xorauth.so -p udp -us 21 -ud 21 ::2
 ==12885== 
 Added 19 options
 Initializing module ipv6
 Initializing module ah
 Initializing module udp
 Finalizing module udp
 Finalizing module ah
 Finalizing module ipv6
 Final packet data:
 60 00 00 00   `...
 00 38 33 20   .83 
 /*rest packet data*/
 73 62 68 64   sbhd
 66 67 68 79   fghy
 68 61 62 63   habc
Freeing module ipv6
Freeing module ah
Freeing module udp
==12885== 
==12885== HEAP SUMMARY:
==12885==     in use at exit: 875 bytes in 7 blocks
==12885==   total heap usage: 115 allocs, 108 frees, 9,587 bytes allocated
==12885== 
==12885== 52 (16 direct, 36 indirect) bytes in 1 blocks are definitely 
lost in loss record 5 of 7
==12885==    at 0x40268A4: malloc (vg_replace_malloc.c:236)
==12885==    by 0x4032ADA: ???
==12885==    by 0x40320EF: ???
==12885==    by 0x804A51D: main (sendip.c:575)
==12885== 
==12885== LEAK SUMMARY:
==12885==    definitely lost: 16 bytes in 1 blocks
==12885==    indirectly lost: 36 bytes in 1 blocks
==12885==      possibly lost: 0 bytes in 0 blocks
==12885==    still reachable: 823 bytes in 5 blocks
==12885==         suppressed: 0 bytes in 0 blocks
==12885== Reachable blocks (those to which a pointer was found) are not shown.
==12885== To see them, rerun with: --leak-check=full --show-reachable=yes
==12885== 
==12885== For counts of detected and suppressed errors, rerun with: -v
==12885== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 35 from 11)

错误究竟在哪里????

实际上我在这里命令链接xorauth.so文件,它填充了一些
  可选字段中的身份验证数据,但无法执行此操作。

运行命令后,在其位置上没有可选的验证数据   valgrind也说definitely lost bytes,但它没有说明问题出在哪里? 我也尝试了valgrind的这种变体:

  udit@udit-Dabba ~ $  valgrind --leak-check=full --show-reachable=yes 
  sendip -v -p ipv6 -f file.txt -6s ::1 -p ah -as 0x20 -aq 0x40 
  -ak "yugal" -am xorauth.so -p udp -us 21 -ud 21 ::2 

  ==12893== Memcheck, a memory error detector
  ==12893== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
  ==12893== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
  ==12893== Command: sendip -v -p ipv6 -f file.txt -6s ::1 -p ah -as 0x20
 -aq 0x40 -ak yugal -am xorauth.so -p udp -us 21 -ud 21 ::2
 ==12893== 
 Added 19 options
 Initializing module ipv6
 Initializing module ah
 Initializing module udp
 Finalizing module udp
 Finalizing module ah
 Finalizing module ipv6
 Final packet data:
 60 00 00 00   `...
 00 38 33 20   .83 
 /*rest packet data*/
 66 67 68 79   fghy
 68 61 62 63   habc

 Freeing module ipv6
 Freeing module ah
 Freeing module udp
 ==12893== 
 ==12893== HEAP SUMMARY:
 ==12893==     in use at exit: 875 bytes in 7 blocks
 ==12893==   total heap usage: 115 allocs, 108 frees, 9,587 bytes allocated
 ==12893== 
 ==12893== 28 bytes in 1 blocks are still reachable in loss record 1 of 7
 ==12893==    at 0x40268A4: malloc (vg_replace_malloc.c:236)
 ==12893==    by 0x400CDE8: _dl_map_object_deps (dl-deps.c:510)
 ==12893==    by 0x40125BA: dl_open_worker (dl-open.c:263)
 ==12893==    by 0x400E4D5: _dl_catch_error (dl-error.c:178)
 ==12893==    by 0x4012145: _dl_open (dl-open.c:555)
 ==12893==    by 0x40408BA: dlopen_doit (dlopenold.c:55)
 ==12893==    by 0x400E4D5: _dl_catch_error (dl-error.c:178)
 ==12893==    by 0x40402CB: _dlerror_run (dlerror.c:164)
 ==12893==    by 0x4040936: dlopen@GLIBC_2.0 (dlopenold.c:77)
 ==12893==    by 0x4032BB3: ???
 ==12893==    by 0x40320EF: ???
 ==12893==    by 0x804A51D: main (sendip.c:575)
 ==12893== 
 ==12893== 33 bytes in 1 blocks are still reachable in loss record 2 of 7
 ==12893==    at 0x40268A4: malloc (vg_replace_malloc.c:236)
 ==12893==    by 0x4004E3E: local_strdup (dl-load.c:162)
 ==12893==    by 0x4007DD8: _dl_map_object (dl-load.c:2183)
 ==12893==    by 0x401255A: dl_open_worker (dl-open.c:226)
 ==12893==    by 0x400E4D5: _dl_catch_error (dl-error.c:178)
 ==12893==    by 0x4012145: _dl_open (dl-open.c:555)
 ==12893==    by 0x40408BA: dlopen_doit (dlopenold.c:55)
 ==12893==    by 0x400E4D5: _dl_catch_error (dl-error.c:178)
 ==12893==    by 0x40402CB: _dlerror_run (dlerror.c:164)
 ==12893==    by 0x4040936: dlopen@GLIBC_2.0 (dlopenold.c:77)
 ==12893==    by 0x4032BB3: ???
 ==12893==    by 0x40320EF: ???

 ==12893== 
 ==12893== 33 bytes in 1 blocks are still reachable in loss record 3 of 7
 ==12893==    at 0x40268A4: malloc (vg_replace_malloc.c:236)
 ==12893==    by 0x400AA70: _dl_new_object (dl-object.c:161)
 ==12893==    by 0x4005F8F: _dl_map_object_from_fd (dl-load.c:957)
 ==12893==    by 0x4007E92: _dl_map_object (dl-load.c:2250)
 ==12893==    by 0x401255A: dl_open_worker (dl-open.c:226)
 ==12893==    by 0x400E4D5: _dl_catch_error (dl-error.c:178)
 ==12893==    by 0x4012145: _dl_open (dl-open.c:555)
 ==12893==    by 0x40408BA: dlopen_doit (dlopenold.c:55)
 ==12893==    by 0x400E4D5: _dl_catch_error (dl-error.c:178)
 ==12893==    by 0x40402CB: _dlerror_run (dlerror.c:164)
 ==12893==    by 0x4040936: dlopen@GLIBC_2.0 (dlopenold.c:77)
 ==12893==    by 0x4032BB3: ???
 ==12893== 
 ==12893== 36 bytes in 1 blocks are indirectly lost in loss record 4 of 7
 ==12893==    at 0x40268A4: malloc (vg_replace_malloc.c:236)
 ==12893==    by 0x4032AF3: ???
 ==12893==    by 0x40320EF: ???
 ==12893==    by 0x804A51D: main (sendip.c:575)
 ==12893== 
 ==12893== 52 (16 direct, 36 indirect) bytes in 1 blocks are definitely
 lost in loss record 5 of 7
 ==12893==    at 0x40268A4: malloc (vg_replace_malloc.c:236)
 ==12893==    by 0x4032ADA: ???
 ==12893==    by 0x40320EF: ???
 ==12893==    by 0x804A51D: main (sendip.c:575)
 ==12893== 
 ==12893== 80 bytes in 1 blocks are still reachable in loss record 6 of 7
 ==12893==    at 0x4025355: calloc (vg_replace_malloc.c:467)   
 ==12893==    by 0x400FC84: _dl_check_map_versions (dl-version.c:300)
 ==12893==    by 0x4012810: dl_open_worker (dl-open.c:269)
 ==12893==    by 0x400E4D5: _dl_catch_error (dl-error.c:178)
 ==12893==    by 0x4012145: _dl_open (dl-open.c:555)
 ==12893==    by 0x40408BA: dlopen_doit (dlopenold.c:55)
 ==12893==    by 0x400E4D5: _dl_catch_error (dl-error.c:178)
 ==12893==    by 0x40402CB: _dlerror_run (dlerror.c:164)

 ==12893==    by 0x4040936: dlopen@GLIBC_2.0 (dlopenold.c:77)
 ==12893==    by 0x4032BB3: ???
 ==12893==    by 0x40320EF: ???
 ==12893==    by 0x804A51D: main (sendip.c:575)
 ==12893== 
 ==12893== 649 bytes in 1 blocks are still reachable in loss record 7 of 7
 ==12893==    at 0x4025355: calloc (vg_replace_malloc.c:467)
 ==12893==    by 0x400A842: _dl_new_object (dl-object.c:77)
 ==12893==    by 0x4005F8F: _dl_map_object_from_fd (dl-load.c:957)
 ==12893==    by 0x4007E92: _dl_map_object (dl-load.c:2250)
 ==12893==    by 0x401255A: dl_open_worker (dl-open.c:226)
 ==12893==    by 0x400E4D5: _dl_catch_error (dl-error.c:178)
 ==12893==    by 0x4012145: _dl_open (dl-open.c:555)
 ==12893==    by 0x40408BA: dlopen_doit (dlopenold.c:55)
 ==12893==    by 0x400E4D5: _dl_catch_error (dl-error.c:178)
 ==12893==    by 0x40402CB: _dlerror_run (dlerror.c:164)
 ==12893==    by 0x4040936: dlopen@GLIBC_2.0 (dlopenold.c:77)
 ==12893==    by 0x4032BB3: ???
 ==12893== 
 ==12893== LEAK SUMMARY:
 ==12893==    definitely lost: 16 bytes in 1 blocks
 ==12893==    indirectly lost: 36 bytes in 1 blocks
 ==12893==      possibly lost: 0 bytes in 0 blocks
 ==12893==    still reachable: 823 bytes in 5 blocks
 ==12893==         suppressed: 0 bytes in 0 blocks
 ==12893== 
 ==12893== For counts of detected and suppressed errors, rerun with: -v
 ==12893== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 35 from 11)

我不明白这个输出我没有在文件夹中看到任何名为dl-error等的文件。 请告诉我解决问题的正确方法。

修改 正如所建议的,我应该使用gcc-g选项来包含调试信息....但问题是我正在使用make命令,实际上这个实现不是由我完成的。它是一个标准的数据包生成工具它有一些错误。我不能等待修复bug,所以我自己动手修复它,因为我的项目因此而陷入其间。所以请告诉我该怎么办呢。是的有make的类似开关,或者我必须在某处更改。因为我第一次遇到这种情况所以不知道make和makefile是如何工作的?如果需要,我可以在这里添加一些文件的内容。

sendip.c(第575行)

  575:       if(!mod->do_opt(opts[longindex].name,gnuoptarg,mod->pack)) {
  576:       printf("go to hell");// added by me but not printed.
  577:       usage=TRUE; 
  578:       }

make命令的输出

  udit@udit-Dabba ~/Downloads/sendip-2.5-mec-2 $ make
  for subdir in mec ; do \
    cd $subdir ;\
    make  ;\
    cd ..  ;\
    done
  make[1]: Entering directory `/home/udit/Downloads/sendip-2.5-mec-2/mec'
  make[1]: Nothing to be done for `all'.
  make[1]: Leaving directory `/home/udit/Downloads/sendip-2.5-mec-2/mec'
  gcc -fPIC -fsigned-char -pipe -Wall -Wpointer-arith -Wwrite-strings -Wstrict-   
  prototypes -Wnested-externs -Winline -Werror -g -Wcast-align - 
  DSENDIP_LIBS=\"/usr/local/lib/sendip\"   -c -o sendip.o sendip.c
  sh -c "if [ `uname` = Linux ] ; then \
  gcc -o sendip -g  -rdynamic -ldl -lm -fPIC -fsigned-char -pipe -Wall 
  -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wnested-externs
  -Winline -Werror -g -Wcast-align -DSENDIP_LIBS=\"/usr/local/lib/sendip\" 
  sendip.o gnugetopt.o gnugetopt1.o compact.o ; \
  elif [ `uname` = SunOS ] ; then \
  gcc -o sendip -g -lsocket -lnsl -lm -ldl -fPIC -fsigned-char -pipe -Wall
  -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wnested-externs
  -Winline -Werror -g -Wcast-align -DSENDIP_LIBS=\"/usr/local/lib/sendip\"
  sendip.o gnugetopt.o gnugetopt1.o compact.o ;\
  else \
  gcc -o sendip -g -rdynamic -lm -fPIC -fsigned-char -pipe -Wall 
  -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wnested-externs
  -Winline -Werror -g -Wcast-align -DSENDIP_LIBS=\"/usr/local/lib/sendip\"
  sendip.o gnugetopt.o gnugetopt1.o compact.o ; \
  fi"
  ./help2man -n "Send arbitrary IP packets" -N >sendip.1

* Makefile的内容:*

   #configureable stuff
   PREFIX ?= /usr/local
   BINDIR ?= $(PREFIX)/bin
   MANDIR ?= $(PREFIX)/share/man/man1
   LIBDIR ?= $(PREFIX)/lib/sendip
   #For most systems, this works
   INSTALL ?= install
   #For Solaris, you may need
   #INSTALL=/usr/ucb/install

   CFLAGS= -fPIC -fsigned-char -pipe -Wall -Wpointer-arith
   -Wwrite-strings \
   -Wstrict-prototypes -Wnested-externs -Winline -Werror -g -Wcast-align \
                    -DSENDIP_LIBS=\"$(LIBDIR)\"
   #-Wcast-align causes problems on solaris, but not serious ones
   LDFLAGS=        -g -rdynamic -lm
   #LDFLAGS_SOLARIS= -g -lsocket -lnsl -lm
   LDFLAGS_SOLARIS= -g -lsocket -lnsl -lm -ldl
   LDFLAGS_LINUX= -g  -rdynamic -ldl -lm
   LIBCFLAGS= -shared
   CC=     gcc

   PROGS= sendip
   BASEPROTOS= ipv4.so ipv6.so
   IPPROTOS= icmp.so tcp.so udp.so
   UDPPROTOS= rip.so ripng.so ntp.so
   TCPPROTOS= bgp.so
   PROTOS= $(BASEPROTOS) $(IPPROTOS) $(UDPPROTOS) $(TCPPROTOS)
   LIBS= libsendipaux.a
   LIBOBJS= csum.o compact.o protoname.o headers.o parseargs.o cryptomod.o crc32.o
   SUBDIRS= mec

   all:    $(LIBS) subdirs sendip $(PROTOS) sendip.1 sendip.spec

   #there has to be a nice way to do this
   sendip: sendip.o        gnugetopt.o gnugetopt1.o compact.o
    sh -c "if [ `uname` = Linux ] ; then \
   $(CC) -o $@ $(LDFLAGS_LINUX) $(CFLAGS) $+ ; \
   elif [ `uname` = SunOS ] ; then \
   $(CC) -o $@ $(LDFLAGS_SOLARIS) $(CFLAGS) $+ ;\
   else \
   $(CC) -o $@ $(LDFLAGS) $(CFLAGS) $+ ; \    
   fi"

   libsendipaux.a: $(LIBOBJS)
    ar vr $@ $?

   subdirs:
    for subdir in $(SUBDIRS) ; do \
            cd $$subdir ;\
            make  ;\
            cd ..  ;\
            done

   protoname.o:    mec/protoname.c
    $(CC) -o $@ -c -I. $(CFLAGS) $+

   headers.o:      mec/headers.c
    $(CC) -o $@ -c -I. $(CFLAGS) $+

   parseargs.o:    mec/parseargs.c
    $(CC) -o $@ -c -I. $(CFLAGS) $+

   cryptomod.o:    mec/cryptomod.c
    $(CC) -o $@ -c -I. $(CFLAGS) $+

   crc32.o: mec/crc32table.h mec/crc32.c
    $(CC) -o $@ -c -I. $(CFLAGS) mec/crc32.c

   mec/crc32table.h: mec/gen_crc32table
    mec/gen_crc32table > mec/crc32table.h

   sendip.1:       ./help2man $(PROGS) $(PROTOS) subdirs VERSION
                    ./help2man -n "Send arbitrary IP packets" -N >sendip.1

   sendip.spec:    sendip.spec.in VERSION
                    echo -n '%define ver ' >sendip.spec
                    cat VERSION >>sendip.spec
                    cat sendip.spec.in >>sendip.spec

    %.so: %.c $(LIBS)
                    $(CC) -o $@ $(CFLAGS) $(LIBCFLAGS) $+ $(LIBS)

   .PHONY: clean install

   clean:
                    rm -f *.o *~ *.so $(PROTOS) $(PROGS) $(LIBS) core gmon.out
                    for subdir in $(SUBDIRS) ; do \
                            cd $$subdir ;\
                            make clean ;\
                            cd ..  ;\
                            done

   veryclean:
                    make clean
                    rm -f sendip.spec sendip.1

   install:                all
                    [ -d $(LIBDIR) ] || mkdir -p $(LIBDIR)
                    [ -d $(BINDIR) ] || mkdir -p $(BINDIR)
                    [ -d $(MANDIR) ] || mkdir -p $(MANDIR)
                    $(INSTALL) -m 755 $(PROGS) $(BINDIR)
                    $(INSTALL) -m 644 sendip.1 $(MANDIR)
                    $(INSTALL) -m 755 $(PROTOS) $(LIBDIR)
                    for subdir in $(SUBDIRS) ; do \
                            cd $$subdir ;\
                            make install ;\
                            cd ..  ;\
                            done


     The problem is coming only with the module xorauth.so ,
     its not performing its work.So tell me how to include some 
     more debugging info ..  

3 个答案:

答案 0 :(得分:5)

这一行:

==12885==    by 0x804A51D: main (sendip.c:575)

表示泄漏的内存分配在sendip.c的第575行(通过在该行上调用的函数,随后调用malloc())。您无法看到该函数的名称,因为它所在的文件未使用调试信息进行编译。


所以违规行是:

if(!mod->do_opt(opts[longindex].name,gnuoptarg,mod->pack)) {

这表示内存泄漏在函数mod->do_opt()内。 do_opt是结构mod中的函数指针,因此您需要找到将此值设置为更深的点。

答案 1 :(得分:3)

Memcheck工具提供的堆栈跟踪可能有多种原因。所有这些都列在Valgrind常见问题解答 - 4.2. The stack traces given by Memcheck (or another tool) aren't helpful. How can I improve them?中。在这种情况下,您在使用共享库时使用dlopendlclose因此很可能在dlclose之后丢弃了调试信息,并且Valgrind无法产生良好的堆栈跟踪。解决方法是避免调用dlclose

  

另外,对于涉及共享对象的泄漏报告,如果是共享对象   在程序终止之前卸载,Valgrind将丢弃   调试信息和错误信息将充满???条目。   这里的解决方法是避免在这些共享上调用dlclose   对象。

答案 2 :(得分:2)

您应该使用调试信息(gcc的-g选项)构建程序和库。如果不这样做,valgrind仍然可以找到泄漏,但无法指出源代码中的错误来自何处。回溯中的???表明调试信息不​​可用 - 其中许多信息应该在调试信息出现时显示函数名称和行号。

相关问题