Reputation: 1374
I'd like to redirect the output of std::cerr
and std::cout
to files. For this purpose, I have used the rdbuf
functions as in the code sample below. Unfortunately, I receive the exception
Exception thrown: read access violation.
*(__imp_std::basic_ios<char,std::char_traits<char> >::rdbuf(...)) was 0xCCCCCCCC.
whenever I try to write anything to std::cout
or std::cerr
.
Here is a code sample that produces my problem:
void redirect()
{
auto t = std::time(nullptr);
auto tm = *std::localtime(&t);
std::ostringstream oss;
oss << std::put_time(&tm, "%Y-%m-%d_%H-%M-%S.log");
auto cerrFileName = "cerr-" + oss.str();
auto coutFileName = "cout-" + oss.str();
std::ofstream cerrFile(cerrFileName, std::ios::ate); // file is created
std::cerr.rdbuf(cerrFile.rdbuf());
std::ofstream coutFile(coutFileName, std::ios::ate); // file is created
std::cout.rdbuf(coutFile.rdbuf());
}
int main()
{
redirect();
std::cout << "Test"; // The exception is thrown here.
return 0;
}
This sample creates two files as it should but does not write anything into neither of them. What am I doing wrong?
Upvotes: 1
Views: 425
Reputation: 136276
std::ofstream
own its buffer and when std::ofstream
objects go out of scope they destroy the buffers, resulting in std::cout
and std::cerr
using invalid pointers to the buffers.
Make sure that the buffers do not get deleted prematurely.
Upvotes: 3
Reputation: 409196
With e.g.
std::cout.rdbuf(coutFile.rdbuf());
you make std::cout
share the same buffer as coutFile
, you only set the pointer.
Unfortunately std::basic_streambuf
is not reference counted. That means when the redirect
function returns then coutFile
is destructed and closed which include destructing the buffer object.
That leaves e.g. std::cout
with a stray pointer to a non-existing buffer object.
The streams you share the buffer objects with needs to have a lifetime over the full program. And before you exit the program you need to restore the original buffers for std::cout
and std::cerr
(rdbuf
returns pointers to the old buffers).
Upvotes: 2