Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Unbelievably Obvious Debugging Tip

by dreadpiratepeter (Priest)
on Apr 27, 2004 at 14:00 UTC ( [id://348480]=perlmeditation: print w/replies, xml ) Need Help??

I wouldn't think to post something so blindingly obvious, but I saw two different experienced developers get bit by this in the last month.
When I put a print in to debug something I always put a delimiter (usually parentheses) around any variable I print out. It makes it clear when there are extra whitespace or newlines around your value.
In both case, the programmers were doing string comparisons against data coming from a file. In both cases there were extra spaces at the ends of lines. In both cases the attempt at debugging was to put  print "$str\n" into the program.
When I suggested that they put parentheses around the variable name, they were instantly enlightened.
I developed this habit a long time ago. As Aristotle said, "Good habits formed at youth make all the difference."
For all of you saying, "well, duh" right now, I apologize for stating the obvious. If it hadn't come up twice in the last month I would never have thought to post it.


-pete
"Worry is like a rocking chair. It gives you something to do, but it doesn't get you anywhere."

Replies are listed 'Best First'.
Re: Unbelievably Obvious Debugging Tip
by Abigail-II (Bishop) on Apr 27, 2004 at 14:29 UTC
    Before everyone starts modifying their programs, modifying all their print statements, I'd like to point old and trusty cat. Everyone knows cat. Not everyone knows its options. -E is very useful in this regard: it makes cat print a $ at the end of each line. Other useful cat options for debugging output: -T which displays tabs as ^I, and -v which will show non-printable and non-ASCII characters using ^ and M- notation. With some versions of cat, cat -vET can also be written as cat -A.

    cat is your friend. Never debug without it!

    Abigail

      I use cat -A for ages. Yes, it is a good thing.

      Also, I often use cat -v to make nonprintable characters printable, so that if there's a C-N it wouldn't mess up my terminal, but if it's only text, it would not change. It's also a great way to see C-M's.

      My only concern with that is people who work from a non-UNIX terminal. As I recall, the closest windows alternative (without loading Cygwin) is type, which of course has none of those options. Personally, I tend to agree with the original poster, I delimit my variables when writing logging or debugging output.
        Man, those Windows users are such lazy bastards. Too damn lazy to install a decent Unix toolkit, and too damn lazy to write a trivial Perl program. All they can do is whine that a solution is too Unix specific (never mind the fact that an open source solution for any Unix toolkit is available, not something we can say about Windows tools, can we?) Djees, you give them Perl - the portable Unix - and they still aren't satisfied.
        #!/usr/bin/perl use strict; use warnings; no warnings qw /syntax/; use Getopt::Long; my ($show_ends, $show_tabs, $show_nonprinting); GetOptions ("A|show-all" => sub {$show_ends = 1; $show_tabs = 1; $show_nonprinting = 1}, "e" => sub {$show_ends = 1; $show_nonprinting = 1}, "E|show-ends" => sub {$show_ends = 1}, "t" => sub {$show_tabs = 1; $show_nonprinting = 1}, "T|show-tabs" => sub {$show_tabs = 1}, "v|show-nonprinting" => sub {$show_nonprinting = 1}, ); while (<>) { chomp; s/([\x80-\xFF])/"M-" . chr (ord ($1) - 0x80)/eg if $show_nonprinti +ng; s/([\x00-\x08])/"^" . chr (ord ($1) + 0x40)/eg if $show_nonprinti +ng; s/([\x0A-\x1F])/"^" . chr (ord ($1) + 0x40)/eg if $show_nonprinti +ng; s/\x7F/^?/g if $show_nonprinti +ng; s/\x09/^I/g if $show_tabs; s/$/\$/ if $show_ends; print "$_\n"; } __END__
        Took less than 15 minutes to write and test.

        Abigail

        Those who work without a decent set of tools get no sympathy from me. Either they are fools, or they work for fools. In both cases, the fool is the one who suffers from reduced productivity, which is as it should be.
      Wow! You learn something new every day. Thanks for the tip!
Re: Unbelievably Obvious Debugging Tip
by eserte (Deacon) on Apr 27, 2004 at 14:33 UTC
    I even always use Data::Dumper for debugging output. So I can also spot (invisible) control characters, and I can also dump complex data structures for free. To safe key strokes I use an emacs macro for this:

    (defun perl-insert-data-dumper () (interactive) (insert "require Data::Dumper; print STDERR \"Line \" . __LINE__ . \ +", File: \" . __FILE__ . \"\\n\" . Data::Dumper->new([],[])->Indent(1 +)->Useqq(1)->Dump; # XXX\n") (forward-char -40) ) (define-key global-map [C-f12] 'perl-insert-data-dumper)

      Allow me to recommend Data::Dump::Streamer instead.

      Yes this blatant advertising. But if you talking about for debugging purposes you might as well use something that gets it right 99.9999% of the time instead of 98% of the time. Oh, and I suspect youll find the output is a lot easier to read. :-)


      ---
      demerphq

        First they ignore you, then they laugh at you, then they fight you, then you win.
        -- Gandhi


      i often use Data::Dumper, too. my macro (vim) is:
      imap ddumper <ESC>gglouse Data::Dumper; $Data::Dumper::Indent = 1; $Da +ta::Dumper::Sortkeys = 1;<ESC>``
      although this is just the use-stuff; maybe i should add a macro for the actual printout.
Re: Unbelievably Obvious Debugging Tip
by pelagic (Priest) on Apr 27, 2004 at 14:16 UTC
    100% agreed!
    It looks obvious but it's often disregarded anyway.
    I even do:
    print "str:$str:\n";

    pelagic
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Unbelievably Obvious Debugging Tip
by TomDLux (Vicar) on Apr 27, 2004 at 15:04 UTC
    Definitely! I got in the habit of single-quoting my variables after getting taking a few hours to notice the extra line of output. Recently I'm getting use Data::Dumper more often, which automates the provision of quotes.

    --
    TTTATCGGTCGTTATATAGATGTTTGCA

Re: Unbelievably Obvious Debugging Tip
by Theo (Priest) on Apr 27, 2004 at 17:34 UTC
    I ran into the same sort of problem when printing several variables on the same line. It wasn't immediately clear where one variable ended and the next one began. I started printing them with a single '^' and with no spaces between each value. That caught several problems for me. ++ dreadpiratepeter.

    -Theo-
    (so many nodes and so little time ... )

Re: Unbelievably Obvious Debugging Tip
by matija (Priest) on Apr 27, 2004 at 16:10 UTC
    Absolutely!

    Here's what I use when I have to dump an array:

    print "(".join(")(",@arr).")\n";
      I prefer:
      local $" = ", "; print "[@arr]\n";

      Abigail

      When I don't use Data::Dumper, I do something like: print join "|", "", $list, $of, $vars, "" with the beginning and ending empty string making join put the separator there.

        Because I often deal with data containing every char on the keyboard, I use:

        print STDERR join("\x1E", @list),"\x1E\n";

        This gives me an output with visible record separators (ASCII 0x1E is actuall "Record Separator") quite cleanly, and I use STDERR to avoid bufferring. Default buffering of STDOUT has bitten my debug routines a few times.

        If I'm working a large project, I use my own little module that exports a number of debugging "tools", including this:

        sub dbg { return unless $DEBUG; my $dump = 0; ($dump = 1 && shift) if ($_[0] eq ':DUMP:'); $LOGFILE = open_logfile(); foreach my $item (@_) { $str = (($dump && ref $item) ? Dumper($item) : $item)."\x1E\n +"; print $LOGFILE POSIX::strftime("%Y%m%d:%H.%M.%S\x1E",localtime +).$str if defined $LOGFILE; print STDERR $str unless $QUIET; } }

        The open_logfile sub returns an opened file handle, or opens a new one if need be, to "DEBUG.LOG". Debug items are written to STDERR unless I set $QUIET, and they are always written to the logfile, prepended by a timestamp.

        And, of course, if I unset $DEBUG, then it's basically a no-op.

        Run the following with 'you stupid foo' as arguments:

        #!/usr/bin/perl use Private::Debug 'dbg'; $Private::Debug::DEBUG = 1; $Private::Debug::QUIET = 0; dbg("Hello there", "You fool"); dbg(':DUMP:', "ARGV:", \@ARGV);

        Results in

        #DEBUG.LOG
        20041214:17.58.22▲Hello there▲
        20041214:17.58.22▲You fool▲
        20041214:17.58.22▲ARGV:▲
        20041214:17.58.22▲$VAR1 = [
                  'you',
                  'stupid',
                  'foo'
                ];
        ▲
        
        #STDERR
        Hello there▲
        You fool▲
        ARGV:▲
        $VAR1 = [
                  'you',
                  'stupid',
                  'foo'
                ];
        ▲
        

        It works quite well. The '?' you might see actually shows up as an upward triangle in a terminal, so it is very clear.

        radiantmatrix
        require General::Disclaimer;
        s//2fde04abe76c036c9074586c1/; while(m/(.)/g){print substr(' ,JPacehklnorstu',hex($1),1)}

Re: Unbelievably Obvious Debugging Tip
by etcshadow (Priest) on Apr 28, 2004 at 02:13 UTC
    In my shell, I just drag my mouse over potential whitespace... if it highlights, then it is whitespace, otherwise not.

    Also, if I'm examining output, I'll pipe it into vi - (rather than more or less), where, again, trailing whitespace is distinguishible in various ways.

    It's personal style, I guess.

    One last thing... if you've got two strings showing as different even though they look, by visual examination, the same... the very first thing you should be doing is a character-by-character diff (many different ways of accomplishing this) and/or looking at them in a hex dump. That's just common sense.

    ------------ :Wq Not an editor command: Wq
Re: Unbelievably Obvious Debugging Tip
by spacewarp (Pilgrim) on Apr 27, 2004 at 19:28 UTC
    I encountered something similar a few years ago, when I was still sending my debugging statements for a cgi script to the web browser. In trying to figure out why "<b>03</b>" was not equal to "<b>03</b>", it took looking at the source to figure out that, due to a bad regexp, I was actually getting "<b>0</b><b>3</b>". In the browser, though, they looked identical.

    Spacewarp

    DISCLAIMER:
    Use of this advanced computing technology does not imply an endorsement
    of Western industrial civilization.
Re: Unbelievably Obvious Debugging Tip
by Aragorn (Curate) on Apr 29, 2004 at 08:28 UTC
    I found this out the hard way, years ago. print "<$something>\n"; has saved me much aggravation and time :-)

    Arjen

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://348480]
Approved by Corion
Front-paged by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (3)
As of 2024-03-19 05:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found