0

My program is printing a couple of random numbers and characters. It will be from some debugging code I've left hanging around. It's probably been indirectly switched on during something I've recently changed. I have no idea where it's coming from even after some quick greps through my libraries.

How can I easily track down the source of a print call?
(it will be one of printf or cout <<)

I'm assuming something similar to gdb spitting out a stack trace for every write to stdout. I'll definitely be taking a preventative approach from now on but just interested possible solutions.

jozxyqk
  • 16,424
  • 12
  • 91
  • 180
  • How about print `__FILE__, __LINE__` in your print/cout statement? – billz Oct 02 '13 at 08:55
  • I don't know where the print/cout statement is, it could be in my current project or any of 5 or 6 libraries it depends on. I'm looking for a generic way to trace the `stdout` write. I could perhaps manipulate the stdio/iostream headers but would prefer a less destructive method. – jozxyqk Oct 02 '13 at 08:57
  • You know, depending on version of visual studio, you might be able to simply step into operator << and insert breakpoint at the bottom level file write operation. Of course, if your libraries use different crts, that's not gonna help you. – SigTerm Oct 02 '13 at 09:17

4 Answers4

3

If you don't have many other console outputs besides the one you are looking for, this is the time to use a debugger. First, write a little sample program using a cout and a printf statement. Debug into the calls to see their implementation, and place a brakpoint there. For printf it is likely you will have to do that in the assembler.
Once you have those breakpoints, run your program in the debugger and wait until the breakpoints get hit - the call stack should tell you where the call to printf/cout is.

Arne Mertz
  • 24,171
  • 3
  • 51
  • 90
2

Macros could help you. In the macro definition you could use __FILE__ and __LINE__ (and other such macro) to print the location information.

Here is an example:

#include <iostream>

#define mycout std::cout <<  __FILE__  << "(" << __LINE__ << ") "
#define cout mycout

int main()
{
    cout << "Hello";
}

It prints the file name and line number followed by your message ("Hello" in this case).

main.cpp(8) Hello

Online Demo

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • 1
    While this is usually a good thing to do from the start, it looks like he has not done that. He would have to rewrite all of his debugging outputs. – Arne Mertz Oct 02 '13 at 08:59
1

strace-plus looks like it would do the job. Especially being able to only trace certain system calls with the -e trace=... option to remove the clutter. You could also ... 2>&1 | grep -C 20 ... to find the exact print call.

This is the given example output of the tool:

write(1, "bar again\n", 10)             = 10
  > write() ../sysdeps/unix/syscall-template.S:82
  > _IO_new_file_write() fileops.c:1277
  > _IO_new_do_write() fileops.c:531
  > _IO_new_file_overflow() fileops.c:889
  > _IO_puts() ioputs.c:40
  > bar() [/home/pgbovine/strace-plus/hello]
  > foo() [/home/pgbovine/strace-plus/hello]
  > main() [/home/pgbovine/strace-plus/hello]
  > __libc_start_main() libc-start.c:258
  > _start() [/home/pgbovine/strace-plus/hello]
jozxyqk
  • 16,424
  • 12
  • 91
  • 180
0

@ArneMertz good idea, thanks!. Using a debugger works well in my case since I don't have too much output before the troublesome print. I just had to figure out how to put a break point on a printf or cout call. This page gave me the answer.

Add a single printf and/or cout call to your main function, compile with debug information, and

gdb program
br main
r
disas

Gives something like this:

Dump of assembler code for function main():
   0x00000000004cdb66 <+0>:     push   %rbp
   0x00000000004cdb67 <+1>:     mov    %rsp,%rbp
   0x00000000004cdb6a <+4>:     push   %r12
   0x00000000004cdb6c <+6>:     push   %rbx
   0x00000000004cdb6d <+7>:     sub    $0x380,%rsp
=> 0x00000000004cdb74 <+14>:    mov    $0x5ae287,%edi
   0x00000000004cdb79 <+19>:    callq  0x4c1cf0 <puts@plt>
...

Where 0x4c1cf0 is the address of printf in this case.

b *0x4c1cf0
c
...
bt

And you land at the next call to printf with the stack trace.

If only there were a nice way to automate this, without the constant c/alt-tab/bt cycle.

jozxyqk
  • 16,424
  • 12
  • 91
  • 180
  • well, it seems you're using the command line debugger - there are graphical debuggers that can make your life a bit easier. Regarding the `c/alt-tab/bt` cycle I assume that is because you are running into many "valid" printf/cout calls. On many debuggers you can add conditions to breakpoints, e.g. constraining the contents of variables. Such features could be of help to filter out the "valid" calls. – Arne Mertz Oct 02 '13 at 09:48
  • @ArneMertz Good call, unfortunately the breakpoint lands without any debug symbols. You might be able to write a `gdb` condition for the printf format, but I had already tried grepping for the print format in the code. – jozxyqk Oct 02 '13 at 10:01