From: Pat Eyler Date: 2002-06-07T01:26:13+09:00 Subject: valgrind and ruby (long) ----------------------------------------------------------------------- Disclaimer: I'm not a strong enough programmer (Ruby or C) to be doing development work on Ruby. Take everything I say with a grain of salt. ----------------------------------------------------------------------- I saw another announcement about valgrind (an open-source memory debugger for x86-GNU/Linux) today, and decided to throw Ruby at it to see what came up. After installing valgrind (a painless process), I ran a small ruby script with it. Here are the important bits: [pate@gnupate RWN]$ valgrind --version valgrind-20020601 [pate@gnupate RWN]$ ruby -v ruby 1.6.7 (2002-03-01) [i686-linux] [pate@gnupate RWN]$ cat scanRURL.rb #!/usr/local/bin/ruby -w class Scanner def initialize(file) @file = File.new(file, "r") @announcements = Array.new @hotTopics = Hash.new end HOT_TOPIC_THRESHOLD = 5 def scan scanForAnnouncements @file.rewind scanForHotTopics end def outputAnnouncements puts "Announcements" puts "~~~~~~~~~~~~~~" @announcements.each do |announcement| puts announcement.subject end print "\n" end def outputHotTopics print "Hot Topics\n" print "~~~~~~~~~~~~\n" @hotTopics.each_pair do |topic, occurance| if occurance >= HOT_TOPIC_THRESHOLD puts topic.subject puts "\tOccured " + occurance.to_s + " times" end end end private # # Look for subjects that are anouncements - ANN denotes an announcement # def scanForAnnouncements @file.each do |line| if line =~ /^Subject:\s(\[?(ANN|Ann|ann).*$)/ @announcements << MailSubject.new($1) end end end # # Look for topics that are discussed more than the HOT_TOPIC_THRESHOLD # def scanForHotTopics @file.each do |line| if line =~ /^Subject:\s(.*)$/ mailSubject = MailSubject.new($1) if @hotTopics.has_key?(mailSubject) occurances = @hotTopics[mailSubject] @hotTopics[mailSubject] = occurances.next else @hotTopics.store(mailSubject, 1) end end end end end class MailSubject include Comparable attr_reader :fullSubject attr_reader :subject def initialize(subject) @subject = subject end def <=>(other) @subject <=> other.subject end def eql?(other) @subject.eql?(other.subject) end def hash subject.hash end def to_s print "Full subject is: " + @fullSubject + "\n" print "Subject is: " + @subject + "\n" end end if $0 == __FILE__ if ARGV.size == 1 file = ARGV[0] scanner = Scanner.new(file) scanner.scan scanner.outputAnnouncements scanner.outputHotTopics else p "USAGE: ./scanList.rb FILE" end end [pate@gnupate RWN]$ valgrind --leak-check=yes ./scanRURL.rb rubylang.0603 ==9689== valgrind-20020601, a memory error detector for x86 GNU/Linux. ==9689== Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward. ==9689== Estimated CPU clock rate is 298 MHz ==9689== For more details, rerun with: -v ==9689== ==9689== Conditional jump or move depends on uninitialised value(s) ==9689== at 0x80659D0: mark_locations_array (gc.c:359) ==9689== by 0x8066523: rb_gc (gc.c:1008) ==9689== by 0x8098629: load_file (ruby.c:857) ==9689== by 0x809830B: proc_options (ruby.c:727) [elided some errors] ==9689== Conditional jump or move depends on uninitialised value(s) ==9689== at 0x80659F7: mark_locations_array (gc.c:364) ==9689== by 0x8066523: rb_gc (gc.c:1008) ==9689== by 0x8098629: load_file (ruby.c:857) ==9689== by 0x809830B: proc_options (ruby.c:727) [elided some errors] ==9689== Conditional jump or move depends on uninitialised value(s) ==9689== at 0x8065B6C: rb_gc_mark (ruby.h:606) ==9689== by 0x8065A37: mark_locations_array (gc.c:379) ==9689== by 0x8066523: rb_gc (gc.c:1008) ==9689== by 0x8098629: load_file (ruby.c:857) [elided some errors] ==9689== Use of uninitialised value of size 4 ==9689== at 0x8065B81: rb_gc_mark (gc.c:452) ==9689== by 0x8065A37: mark_locations_array (gc.c:379) ==9689== by 0x8066523: rb_gc (gc.c:1008) ==9689== by 0x8098629: load_file (ruby.c:857) [elided some errors] ==9689== Use of uninitialised value of size 4 ==9689== at 0x8065B81: rb_gc_mark (gc.c:452) ==9689== by 0x8065A37: mark_locations_array (gc.c:379) ==9689== by 0x8066523: rb_gc (gc.c:1008) ==9689== by 0x8098629: load_file (ruby.c:857) [the errors continue ... skipping to the end] ==9689== More than 30000 total errors detected. I'm not reporting any more. ==9689== Final error counts will be inaccurate. Go fix your program! ==9689== [output of command elided] ==9689== ==9689== ERROR SUMMARY: 30000 errors from 37 contexts (suppressed: 0 from 0) ==9689== malloc/free: in use at exit: 379208 bytes in 8308 blocks. ==9689== malloc/free: 82108 allocs, 73800 frees, 3639387 bytes allocated. ==9689== For counts of detected errors, rerun with: -v ==9689== searching for pointers to 8308 not-freed blocks. ==9689== checked 4608320 bytes. ==9689== ==9689== definitely lost: 0 bytes in 0 blocks. ==9689== possibly lost: 20 bytes in 1 blocks. ==9689== still reachable: 379188 bytes in 8307 blocks. ==9689== ==9689== 20 bytes in 1 blocks are possibly lost in loss record 1 of 6 ==9689== at 0x40042D79: malloc (in /opt/lib/valgrind/valgrind.so) ==9689== by 0x806550D: ruby_xmalloc (gc.c:97) ==9689== by 0x80869AC: top_local_setup (parse.y:4800) ==9689== by 0x807ACDC: rb_yyparse (parse.y:286) ==9689== ==9689== LEAK SUMMARY: ==9689== possibly lost: 20 bytes in 1 blocks. ==9689== definitely lost: 0 bytes in 0 blocks. ==9689== still reachable: 379188 bytes in 8307 blocks. ==9689== Reachable blocks (those to which a pointer was found) are not shown. ==9689== To see them, rerun with: --show-reachable=yes ==9689==