On Wed, 27 Oct 2021 at 09:27, Jay Feldblum via Libstdc++ < libstdc++@gcc.gnu.org> wrote: > From: yfeldblum > > The stdout stream is reserved for output intentionally produced by the > application. Assertion failures and other forms of logging must be > emitted to stderr, not to stdout. > > It is common for testing and monitoring infrastructure to scan stderr > for errors, such as for assertion failures, and to collect or retain > them for analysis or observation. It is a norm that assertion failures > match this expectation in practice. > > While `__builtin_fprintf` is available as a builtin, there is no > equivalent builtin for `stderr`. The only option in practice is to use > the macro `stderr`, which requires `#include `. It is desired > not to add such an include to `bits/c++config` so the solution is to > write and export a function which may be called by `bits/c++config`. > > This is expected to be API-compatible and ABI-compatible with caveats. > Code compiled against an earlier libstdc++ will work when linked into a > later libstdc++ but the stream to which assertion failures are logged is > anybody's guess, and in practice will be determined by the link line and > the choice of linker. This fix targets builds for which all C++ code is > built against a libstdc++ with the fix. > Thanks for the patch! Comments below. > > Alternatives: > * This, which is the smallest change. > * This, but also defining symbols `std::__stdin` and `std::__stdout` for > completeness. > * Define a symbol like `std::__printf_stderr` which prints any message > with any formatting to stderr, just as `std::printf` does to stdout, > and call that from `std::__replacement_assert` instead of calling > `__builtin_printf`. > * Move `std::__replacement_assert` into libstdc++.so and no longer mark > it as weak. This allows an application with some parts built against a > previous libstdc++ to guarantee that the fix will be applied at least > to the parts that are built against a libstdc++ containing the fix. > > libstdc++-v3/ChangeLog: > include/bits/c++config (__glibcxx_assert): print to stderr. > --- > libstdc++-v3/include/bits/c++config | 8 ++++-- > libstdc++-v3/src/c++98/Makefile.am | 1 + > libstdc++-v3/src/c++98/Makefile.in | 2 +- > libstdc++-v3/src/c++98/stdio.cc | 39 +++++++++++++++++++++++++++++ > 4 files changed, 47 insertions(+), 3 deletions(-) > create mode 100644 libstdc++-v3/src/c++98/stdio.cc > > diff --git a/libstdc++-v3/include/bits/c++config > b/libstdc++-v3/include/bits/c++config > index > a64958096718126a49e8767694e913ed96108df2..d821ba09d88dc3e42ff1807200cfece71cc18bd9 > 100644 > --- a/libstdc++-v3/include/bits/c++config > +++ b/libstdc++-v3/include/bits/c++config > @@ -523,6 +523,10 @@ namespace std > # ifdef _GLIBCXX_VERBOSE_ASSERT > namespace std > { > + // Avoid the use of stderr, because we're trying to keep the > + // include out of the mix. > + extern "C++" void* __stderr() _GLIBCXX_NOEXCEPT; > We can declare this locally in __replacement_assert, so it isn't made visible in namespace std. + > // Avoid the use of assert, because we're trying to keep the > // include out of the mix. > extern "C++" _GLIBCXX_NORETURN > @@ -531,8 +535,8 @@ namespace std > const char* __function, const char* __condition) > _GLIBCXX_NOEXCEPT > { > - __builtin_printf("%s:%d: %s: Assertion '%s' failed.\n", __file, > __line, > - __function, __condition); > + __builtin_fprintf(__stderr(), "%s:%d: %s: Assertion '%s' failed.\n", > + __file, __line, __function, __condition); > __builtin_abort(); > } > } > diff --git a/libstdc++-v3/src/c++98/Makefile.am > b/libstdc++-v3/src/c++98/Makefile.am > index > b48b57a2945780bb48496d3b5e76de4be61f836e..4032f914ea20344f51f2f219c5575d2a3858c44c > 100644 > --- a/libstdc++-v3/src/c++98/Makefile.am > +++ b/libstdc++-v3/src/c++98/Makefile.am > @@ -136,6 +136,7 @@ sources = \ > math_stubs_float.cc \ > math_stubs_long_double.cc \ > stdexcept.cc \ > + stdio.cc \ > I think adding it to src/c++11/debug.cc makes sense. That file already uses stderr itself, and is where we define other utilities for printing assertions. We also need to add it to the linker script, so that the symbol gets exported from the shared library. Otherwise any use of -D_GLIBCXX_ASSERTIONS or -D_GLIBCXX_DEBUG results in linker errors. The attached patch does that.