0

I have a large code and it is not obvious when it is creating an output file. Is there a way in gdb to put a breakpoint when a new ofstream is created? Or when a file is written to?

I've tried things like

(gdb) b ofstream
Function "ofstream" not defined.
Make breakpoint pending on future shared library load? (y or [n]) n
(gdb) b std::ofstream
Function "std::ofstream" not defined.
Make breakpoint pending on future shared library load? (y or [n]) n

I want to do this so that I can get a backtrace to find out which functions are creating this file.

I also tried

(gdb) catch syscall write

This works except it also catches the output to the screen (and the output to stdout is verbose), when really I want to catch the output to a file.

EDIT: Here is a minimal working example.

#include <iostream>
#include <fstream>
using namespace std;

int main () {
  cout << "hello world\n" ;
  ofstream myfile;
  myfile.open ("example.txt");
  myfile << "Writing this to a file.\n";
  myfile.close();
  return 0;
}
irritable_phd_syndrome
  • 4,631
  • 3
  • 32
  • 60

2 Answers2

2

This works except it also catches the output to the screen

You can exclude output to stdout with conditional breakpoint. On x86_64 this can be done with comparing rdi register to 1:

(gdb) catch syscall write
Catchpoint 1 (syscall 'write' [1])
(gdb) condition 1 $rdi!=1
(gdb) i b
Num     Type           Disp Enb Address            What
1       catchpoint     keep y                      syscall "write" 
    stop only if $rdi!=1
(gdb) 

You can also set conditional breakpoint on exact file descriptor you want. See https://stackoverflow.com/a/8052681/72178 how to map file name to file descriptor on Linux.

ks1322
  • 33,961
  • 14
  • 109
  • 164
0

Unfortunately you have to provide the complete function prototype. But gdb can give you a list of available methods and functions. If you type (note the single quote)

(gdb) break 'std::

you can invoke the auto-completion with tabulator. This will return a list of all gdb known methods and functions under namespace std. In your case (ofstream) you will find following entry in the list:

std::basic_ofstream<char, std::char_traits<char> >::basic_ofstream(char const*, std::_Ios_Openmode)```

Now just set the breakpoint with following command:

(gdb) break std::basic_ofstream<char, std::char_traits<char> >::basic_ofstream(char const*, std::_Ios_Openmode)

run it and it should work as expected.

  • It appears that your suggestion does not work with the MWE that I just added to the questions. – irritable_phd_syndrome Mar 27 '18 at 11:10
  • just tried the MWE (compiled with g3 debug flag) and it works. Did you select the right constructor (std::basic_ofstream >::basic_ofstream()) and compile with the proper flags? – Stefan Moosbrugger Mar 27 '18 at 11:43
  • Using `g++ -g3 -c test.cpp -o test.o`; `g++ test.o -o test` with gcc 4.9.2 on CentOS 6.6, it doesn't work. I copied and pasted the last line of code above (excluding `(gdb)`). – irritable_phd_syndrome Mar 27 '18 at 12:06
  • it seems you are setting the breakpoint on the wrong call. std::basic_ofstream >::basic_ofstream() is the right one (default ofstream constructor). the constructor i mentioned in the answer is a non default constructor that expects two arguments (i think the MWE was not there when i wrote the answer, so i took one as an example). – Stefan Moosbrugger Mar 27 '18 at 20:24