15

I have a program where I use cout to emit debug information. The code is executed in the initialization of a static global variable, i.e. quite early in the program execution. When I use my own build script to build the program, it segfaults at the first use of cout (only a string literal is shifted into cout, so it cannot be the value). I used valgrind to check for earlier writes to invalid locations, but there are none (and there is also no code that would be likely to generate those writes, I dont do too much before the output). When I copy the source code to an eclipse project and let the eclipse built-in builder build it, then everything works fine. I used no weird builder settings simply compiled with -ggdb -std=c++0x, these are the only two flags.

So what can be the reason that a cout with a string literal segfaults, if there were no invalid writes before? How can the build configuration affect this?

(I am sorry I can give you no minimal example, as this example would simply compile fine at your machine, as it does for me when using the eclipse builder)

Edit: Here is the stacktrace:

0x00007ffff7b6d7d1 in std::ostream::sentry::sentry(std::ostream&) () from /usr/lib   /x86_64-linux-gnu/libstdc++.so.6
(gdb) backtrace
#0  0x00007ffff7b6d7d1 in std::ostream::sentry::sentry(std::ostream&) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x00007ffff7b6dee9 in std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long) ()
from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#2  0x00007ffff7b6e2ef in std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) ()
  from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00000000004021be inTest::fill (this=0x6120f8, funcs=...) at inTest.cpp:92

The last frame is my code. Line 92 simply reads:

std::cout << "Test";
gexicide
  • 38,535
  • 21
  • 92
  • 152

3 Answers3

16

As Luchian has pointed out, you cannot use std::cout before the first instance of ios_base::Init has been constructed. You don't have to define an instance, however; including <iostream> should be enough.

Order of initialization is defined within a single translation unit. If you include <iostream> at the top of all files which have static instances, you should be OK. If the constructor of a static object calls a function in another translation unit, however, and the output is in that translation unit, it is not sufficient to include <iostream> only in the translation unit which does the output. You must include it in the translation unit where the static variable(s) are defined. Even if they don't do any output.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • That was my problem! One static called a method of another translation unit and only that other translation unit included . I moved the include of into the header in able to make sure that every translation unit that includes the called function also includes . Now it works. – gexicide Sep 07 '12 at 13:49
  • 1
    @gexicide: I could go a bit further and say that your problem is actually having static variables and dependencies on the order of initialization. What you say was your problem is actually the symptoms. – David Rodríguez - dribeas Sep 07 '12 at 14:12
  • 1
    @DavidRodríguez-dribeas: I do not have order of initialization problems with my own code. I was just debugging some nasty bug in the initialization and used `cout`s for it (I know, a debugger is usually better, but sometimes simply dumping out some debug text is better) – gexicide Sep 07 '12 at 14:24
  • @DavidRodríguez-dribeas There are (today) more or less standard idioms which you can use to avoid this sort of problem. `std::cout` doesn't use them, however. And his problem involved the order of initialization between his objects and `std::cout`. – James Kanze Sep 07 '12 at 14:56
  • @gexicide: From the description you provided: *one static called a method of another translation unit*, and that function in another translation unit depends on another static (`cout`). The moment that one static variable depends on *anything* (static object or function or otherwise) you are opening the door for the static initialization order fiasco – David Rodríguez - dribeas Sep 07 '12 at 15:01
  • @JamesKanze: Can you point me to what idioms do solve the static initailization order fiasco? (Other than not having namespace/class level static variables?) – David Rodríguez - dribeas Sep 07 '12 at 15:02
  • 1
    @DavidRodríguez-dribeas: Yes, but the problem only existed during debugging. I wanted to point out that the original code is not flawed and I will surely not rewrite the code into not using statics only because it fails with debug `cout`s :). – gexicide Sep 07 '12 at 15:48
  • @DavidRodríguez-dribeas The usual idiom today is the singleton pattern, where the initialization actually occurs in a function (and so occurs the first time the function is called). If iostream were being designed today, who knows. Perhaps we'd have to write `std::cout()`. – James Kanze Sep 07 '12 at 16:38
  • @JamesKanze: Ah, ok, I knew that one, and it is not bulletproof either. It guarantees that the order of construction won't cause an issue, but it does not guarantee that the order of destruction will not cause it. That is if a static object depends on a different static object during destruction but not during construction, then the static local trick won't cut it. Then you can jump into the *phoenix* singleton that Alexandrescu wrote in Modern C++ Design and all that... but that brings it's own problems. I am not sure that the approach with `cout` is not better than the local static one... – David Rodríguez - dribeas Sep 07 '12 at 16:45
  • ... that is, it is guaranteed to work unless your static object depends on a function in a different translation unit and you are not including the `` header in your translation unit. The problem is still that the static initialization is not self contained in a single translation unit. – David Rodríguez - dribeas Sep 07 '12 at 16:49
  • @DavidRodríguez-dribeas In the usual singleton idiom, the object is never destructed. (An the standard requires that `std::cout` never be destructed.) The idiom used by `std::cout` _is_ less secure, which is why the singleton idiom has become preferred. – James Kanze Sep 07 '12 at 17:04
  • +infinity for being exactly what I needed, comprehensively explaining why I was getting a segfault when a ctor used cout, but including in a seemingly distant hpp fixed it. Turns out the ctor was invoked in a static variable, in a different cpp which included the other hpp. Adding to the cpp defining the variable sorted it. Btw, the cout in ctor is only for debugging, I've commented why is included in the static def file, and I've added a link to your post, too :-) – underscore_d Jul 14 '15 at 22:03
14

std::cout is an object in static storage. It's guaranteed to be initialized before entering main, but not necessarily before other statics in your code. Seems like the static initialization order fiasco.

After some digging:

27.4.2.1.6 Class ios_base::Init

Init ();

3) Effects: Constructs an object of class Init. If init_cnt is zero, the function stores the value one in init_- cnt , then constructs and initializes the objects cin, cout, cerr, clog (27.3.1), wcin, wcout, wcerr, and wclog (27.3.2). In any case, the function then adds one to the value stored in init_cnt .

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
0

Static variable initialization is a no-man's-land. You will avoid problems if you avoid doing significant work there. Maybe you should wrap the static variable in a Singleton pattern so you can defer initialization to the first time it's used.

japreiss
  • 11,111
  • 2
  • 40
  • 77