Stop bycatch of <stdio.h> definitions caused by C++ includes - c++

In a comment to another answer, I was shown a code example that seemingly used printf and puts without including <stdio.h> but the online compiler didn't complain.[1] To understand what's going on, I copied it to my local IDE.
Reduced to relevant includes and output, it's basically this:
#include <string>
#include <map>
#include <optional>
int main() {
printf("Answer %d\n", 42);
puts("Question?");
}
Experimenting with gcc 8.1.0 (packaged with Clode::Blocks 20.03), I found out, that the includes can be further reduced to
<string> or <map> or <optional> in C++17 (ISO/GCC)
<string> or <map> in C++11/C++14 (ISO/GCC)
<string> in C++98 (ISO/GCC)
Also a sample test - C++14 (gcc 8.3) - on ideone.com compiles and runs fine:
#include <iostream>
int main() {
printf("printf without #include <stdio.h>\n");
return 0;
}
This is also true for other definitions from <stdio.h> like FILE.
I found no information at cppreference.com
std::printf, std::fprintf, std::sprintf, std::snprintf - cppreference.com
std::puts - cppreference.com
printf, fprintf, sprintf, snprintf, printf_s, fprintf_s, sprintf_s, snprintf_s - cppreference.com
puts - cppreference.com
I also tried several web and SO searches but wasn't successful so far.
While it may be handy for small examples to get some powerful functions for free, but a serious project may suffer from it: besides comparatively easy to fix compiler errors, I see the danger of serious runtime errors.
How can I effectively control/prevent this kind of inclusion?
[1] the referenced code now contains the include statement, but I'm pretty sure that it didn't at stage I copied it .. or maybe I copied just a portion of it? ... anyway the observed behavior is there as described above.

I am afraid you cannot.
The standard requires that the well known include files declare the relevant names, but does not prevent them to include other files/names, if the library implementation finds it useful.
Said differently, after including iostream you are sure that all the names belonging to it are correctly declared, but you cannot know (except by examining the file itself) if other names have been defined, or if other standard files have been included. Here, your implementation chooses to automatically include stdio.h, but a different (standard library) implementation could choose not to include it. You have reached the world of unspecifiedness...

Aside from any arguments about "purity", I don't see how including the declarations for these functions could in any way be harmful. As a matter of fact, not having them and letting the compiler implicitly assuming int printf() – albeit only C compilers do it, C++ won't – is calling for trouble.
printf is part of the C language standard. And although C++ isn't C, there's so much overlap between their ecosystems, that C++ considers printf as part of the implementation runtime environment as well, as it does with all the other functions from the C standard library.
And as such, all of these symbols are reserved. Outside of actually implementing the runtime library itself, you have no business defining symbols of those names yourself.
#include preprocessor directives are just inline text substitution with text pulled in from an additional file.
(extern) symbol declarations will not create symbols of those names, but they will make sure, that you're not going to redefine those symbols at your own.
So I really don't see where your worries about runtime errors do come from.

Related

How can I determine what header calls another header in c++?

I am reading from here : Can std::string be used without #include <string>?, <iostream> is calling <string>. But I do not see any includes of <string> in Standard library header <iostream> from c++ standard: https://en.cppreference.com/w/cpp/header/iostream. In <iostream> is only included <ios>, <streambuf>, <istream> and <ostream> according to that documentation. So this code works (file foo.cpp):
#include <iostream>
int main(){
std::cout << "enter srting\n";
std::string out; //std::string should not be included according to standard documentation
std::cin >> out;
std::cout << "test, " << out;
}
But I have to try to see dependecies generated from gcc:
cc -H foo.cpp |& vim -
and the output is (I have regex out files with string in it):
. /usr/include/c++/8/iostream
..... /usr/include/c++/8/bits/stringfwd.h
...... /usr/include/c++/8/string
....... /usr/include/c++/8/bits/basic_string.h
........ /usr/include/c++/8/ext/string_conversions.h
....... /usr/include/c++/8/bits/basic_string.tcc
So I can see that in the end, many "string" headers are indeed included
(so should I trust that documentation, when the did not mentioned <string> header in "Includes" list of <iostream>?).
Some of them are deeper on the #include stack (term from gcc manual), which brings me to question,
what calls what? And what is the "true" header, that define std::string of them? (is it /usr/include/c++/8/bits/basic_string.h?...)
from this question Why does omission of "#include <string>" only sometimes cause compilation failures?, they mentioned:
Some compilers on some platforms may on some time of the month compile even though you failed to include the header
But from the upper output of the "string headers", there is multiple of them , so how's possible for a compiler to compile only sometimes? Which of these headers are really important for successful compilation?
How to orient in cpp headers, which are meaningful for compiler, and could be tracked their "#include stack" (i.e. other meaningful headers)?
EDIT:
If it depends on my specific implementation of my stdlib++, then I want to know how can I determine from source whether that inclusion is made before I try to compile. Not by "If it compiles, then it works".
In general you cannot know what headers are transitively included by the headers you include, and any standard header is allowed to, but not required to, include any other header. And you shouldn't rely on transitive includes ever. You should include the headers you need for the things that you use and then you'll be good.
You should always check the documentation for any symbol you use and include any headers it is specified to require.
The C++ standard only specifies which symbols must be made available when a standard header is included. It does not place any limits on what other symbols are made available. In your example, the standard specifies the <iostream> must include <ios>, <streambuf>, <istream>, and <ostream>, but <iostream> may include any other headers its authors want. It may also forward-declare any symbols it may need.
(so should I trust that documentation, when the did not mentioned <string> header in "Includes" list of <iostream>?).
You should trust that the symbols specified as being available when you include <string> will be. That is all. You may not assume that those symbols will not be visible when including any other header.
what calls what? And what is the "true" header, that define std::string of them? (is it /usr/include/c++/8/bits/basic_string.h?...)
This is an implementation detail that can only be answered by inspecting the implementation's headers. Libstdc++ (the standard library implementation used by GCC) has the declaration of the std::string class in bit/stringfwd.h and its definition in bits/basic_string.h and bits/basic_string.tcc (for the current version, at least), but that is not required at all. If the libstdc++ maintainers decided they wanted to refactor and reorganize things, they would be free to do so. The only requirement that is guaranteed by the C++ language is that std::string must be available when <string> is included.
But from the upper output of the "string headers", there is multiple of them, so how's possible for a compiler to compile only sometimes?
Different standard library implementations or different versions of the same implementation could transitively include different headers. Different compiler flags (i.e. a debug flag or different standard compliance mode) could transitively include different headers.
Which of these headers are really important for successful compilation?
How to orient in cpp headers, which are meaningful for compiler, and could be tracked their "#include stack" (i.e. other meaningful headers)?
All of them are meaningful. The standard library's authors wouldn't include a header if they didn't need it for something. Just because you aren't using any symbols declared/defined in that header directly doesn't mean none are being used.
EDIT: If it depends on my specific implementation of my stdlib++, then I want to know how can I determine from source whether that inclusion is made before I try to compile. Not by "If it compiles, then it works".
The only way to know is to look at your standard library implementation's headers. There is nothing magical about them; they're just C++ code. If you want to know if <iostream> includes a declaration or definition of std::string, open your implementation's copy of <iostream> and look for a declaration or definition of std::string. Repeat this process for any headers that <iostream> includes.
<iostream> is calling <string>
Do you mean that it includes <string>? Calling is something that is done to functions.
But I do not see any includes of <string> in Standard library header <iostream> from c++ standard: https://en.cppreference.com/w/cpp/header/iostream.
What you're reading is documentation of <iostream>. Indeed, <iostream> is not documented to include <string>.
So this code works (file foo.cpp):
It may work with some standard library implementation. It may not work using other implementations.
(so should I trust that documentation, when the did not mentioned <string> header in "Includes" list of <iostream>?).
cppreference is fairly high quality. Unless it contradicts the standard, it is fairly safe to assume that it is correct. Indeed in this regard it is correct: <iostream> is not guaranteed to include <string>.
what calls what?
Some headers include some other headers. There is no need to know more accurately than that because you should not rely on transitive inclusions (except those that are documented).
And what is the "true" header, that define std::string of them?
As per documentation, std::string is defined in header named string (commonly stylised as <string> which matches the conventional inclusion syntax).
so how's possible for a compiler to compile only sometimes?
It could ask the current time from the operating system and use a branch to do one thing or another depending on that time. Compilers don't typically do that, but the point is that they could.
More realistically, you may at some point need to compile your program using another (version) of the compiler (or standard library implementation). Different implementations behave different from one another.
Which of these headers are really important for successful compilation?
The ones that are documented to define and declare the names whose definitions and declarations your program relies on. If you use std::string, then you must include the header that defines std::string which is <string>.

Should I include <tuple>?

I am a newbie in c++, and I suspect, that, of course the question relates not only to tuple.
So, I've watched a tutorial with roughly this code:
#include <tuple>
std::tuple<...> t(...)
Why #include <tuple>? Especially, given the fact that we explicitly write std::tuple. The code compiles without that #include line just well...
Because <tuple> is a header file which contains the tuple class inside the namespace std. Just because you're explicitliy saying std:: doesn't mean the compiler will just be able to find it if it's not included.
The reason it worked for you in this case is probably because another header you have included already includes <tuple> and thus your code includes <tuple> indirectly or because the compiler you're building with includes it automatically. This is not guaranteed by the standard and should not be relied upon. Always include the headers you'll need to make your code portable.
You always should include the specific headers for any types that you use in your code.
The code compiles without that #include line just well...
That your code compiles without is just by chance, because it might have been included by another standard header you use in your program, and not guaranteed by the standard, and thus not portable.
Especially, given the fact that we explicitly write std::tuple.
The explicit use of the std:: namespace doesn't have any significance about that rule.
You should also always be explicit about using classes or types from the std namespace to prevent getting into ambiguity troubles.
Related stuff:
Why is “using namespace std;” considered bad practice?
Why should I not #include ?
How do I include the string header?
In C++ you need to include the header for everything you use. The std:: is about the namespace, it's completely different.
Apparently your compiler is smart enough to deal with it, but most of the compilers won't.
Some standard headers shall include other standard headers according to the C++ Standard. For example the header <algorithm> must include the header <initializer_list>.
However implementations are allowed to include standard headers in other standard headers at their discretion.
You should not rely on this because your program compiled with one compiler will not compile using another compiler.
Even if one standard header is included in another standard header according to the requirements of the C++ Standard nevertheless it is a good practice to include such a header explicitly because the user of the program (some other programmer) should bother about dependencies of the headers and will be free to include or exclude other headers.

Is it OK to put a standard, pure C header #include directive inside a namespace? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is it a good idea to wrap an #include in a namespace block?
I've got a project with a class log in the global namespace (::log).
So, naturally, after #include <cmath>, the compiler gives an error message each time I try to instantiate an object of my log class, because <cmath> pollutes the global namespace with lots of three-letter methods, one of them being the logarithm function log().
So there are three possible solutions, each having their unique ugly side-effects.
Move the log class to it's own namespace and always access it with it's fully qualified name. I really want to avoid this because the logger should be as convenient as possible to use.
Write a mathwrapper.cpp file which is the only file in the project that includes <cmath>, and makes all the required <cmath> functions available through wrappers in a namespace math. I don't want to use this approach because I have to write a wrapper for every single required math function, and it would add additional call penalty (cancelled out partially by the -flto compiler flag)
The solution I'm currently considering:
Replace
#include <cmath>
by
namespace math {
#include "math.h"
}
and then calculating the logarithm function via math::log().
I have tried it out and it does, indeed, compile, link and run as expected. It does, however, have multiple downsides:
It's (obviously) impossible to use <cmath>, because the <cmath> code accesses the functions by their fully qualified names, and it's deprecated to use in C++.
I've got a really, really bad feeling about it, like I'm gonna get attacked and eaten alive by raptors.
So my question is:
Is there any recommendation/convention/etc that forbid putting include directives in namespaces?
Could anything go wrong with
diferent C standard library implementations (I use glibc),
different compilers (I use g++ 4.7, -std=c++11),
linking?
Have you ever tried doing this?
Are there any alternate ways to banish the math functions from the global namespace?
I've found several similar questions on stackoverflow, but most were about including other C++ headers, which obviously is a bad idea, and those that weren't made contradictory statements about linking behaviour for C libraries. Also, would it be beneficial to additionally put the #include <math.h> inside extern "C" {}?
edit
So I decided to do what probably everyone else is doing, and put all of my code in a project namespace, and to access the logger with it's fully qualified name when including <cmath>.
No, the solution that you are considering is not allowed. In practice what it means is that you are changing the meaning of the header file. You are changing all of its declarations to declare differently named functions.
These altered declarations won't match the actual names of the standard library functions so, at link time, none of the standard library functions will resolve calls to the functions declared by the altered declarations unless they happen to have been declared extern "C" which is allowed - but not recommended - for names which come from the C standard library.
ISO/IEC 14882:2011 17.6.2.2/3 [using.headers] applies to the C standard library headers as they are part of the C++ standard library:
A translation unit shall include a header only outside of any external declaration or definition[*], and shall include the header lexically before the first reference in that translation unit to any of the entities declared in that header.
[*] which would include a namespace definition.
Why not putting a log class in it's own namespace and using typedef namespace::log logger; to avoid name clashes in a more convenient way?
Change your class's name. Not that big of a deal. ;-)
Seriously though, it's not a great idea to put names in the global namespace that collide with names from any standard header. C++03 didn't explicitly permit <cmath> to define ::log. But implementations were chronically non-conforming about that due to the practicalities of defining <cmath> on top of an existing <math.h> (and perhaps also an existing static-link library for some headers, including math). So C++11 ratifies existing practice, and allows <cmath> to dump everything into the global namespace. C++11 also reserves all those names for use with extern "C" linkage, and all function signatures for use with C++ linkage, even if you don't include the header. But more on that later.
Because in C++ any standard header is allowed to define the names from any other standard header (i.e, they're allowed to include each other), this means that any standard header at all can define ::log. So don't use it.
The answer to your question about different implementations is that even if your scheme works to begin with (which isn't guaranteed), in some other implementation there might be a header that you use (or want to use in future in the same TU as your log class), that includes <cmath>, and that you didn't give the namespace math treatment to. Off the top of my head, <random> seems to me a candidate. It provides a whole bunch of continuous random number distributions that plausibly could be implemented inline with math functions.
I suggest Log, but then I like capitalized class names. Partly because they're always distinct from standard types and functions.
Another possibility is to define your class as before and use struct log in place of log. This doesn't clash with the function, for reasons that only become clear if you spend way too much time with the C and C++ standards (you only use log as a class name, not as a function and not as a name with "C" linkage, so you don't infringe on the reserved name. Despite all appearances to the contrary, class names in C++ still inhabit a parallel universe from other names, rather like struct tags do in C).
Unfortunately struct log isn't a simple-type-identifier, so for example you can't create a temporary with struct log(VERY_VERBOSE, TO_FILE). To define a simple-type-identifier:
typedef struct log Log;
Log(VERY_VERBOSE, TO_FILE); // unused temporary object
An example of what I say in a comment below, based on a stated example usage. I think this is valid, but I'm not certain:
#include <iostream>
#include <cmath>
using std::log; // to enforce roughly what the compiler does anyway
enum Foo {
foo, bar
};
std::ostream &log(Foo f) { return std::cout; }
int main() {
log(foo) << log(10) << "\n";
}
It is ugly hack too, but I believe will not cause any linker problems. Just redefine log name from <math.h>
#define log math_log
#include <math.h>
#undef log
It could cause problems with inline functions from math using this log, but maybe you'd be lucky...
Math log() is still accessible but it's not easy. Within functions where you want to use it, just repeat its real declaration:
int somefunc() {
double log(double); // not sure if correct
return log(1.1);
}

In what cases we need to include <cassert>?

In what cases should we include cassert?
In short, don't use it; use <assert.h>.
C++11 removed any formal guarantee of a "c...." header not polluting the global namespace.
It was never an in-practice guarantee, and now it's not even a formal guarantee.
Hence, with C++11 there is no longer any conceivable advantage in using the "c...." header variants, while there is the distinct and clear disadvantage that code that works well with one compiler and version of that compiler, may fail to compile with another compiler or version, due to e.g. name collisions or different overload selection in the global namespace.
SO, while cassert was pretty meaningless in C++03 (you can't put a macro in a namespace), it is totally meaningless -- even as a special case of a general scheme -- in C++11.
Addendum, Dec 22 2013:
The standard defines each C++ C header <X.h> header in terms of the <cX> header, which in turn is defined in terms of the corresponding C library header.
C++11 §D.5/2:
“Every C header, each of which has a name of the form name.h, behaves as if each name placed in the standard library namespace by the corresponding cname header is placed within the global namespace scope.”
C++11 §D.5/3 (non-normative example):
“The header <cstdlib> assuredly provides its declarations and definitions within the namespace std. It may also provide these names within the global namespace. The header <stdlib.h> assuredly provides the same declarations and definitions within the global namespace, much as in the C Standard. It may also provide these names within the namespace std.”
Stack Overflow user C.R.’s comment made me aware that some versions of g++, such as MinGW g++ 4.7.2, are quite non-standard with respect to the <X.h> headers, lacking the overloads of e.g. sin that the C++ standard requires:
I already knew that MinGW g++ 4.7.2 also entirely lacks functions such as swprintf, and that it has ditto shortcomings in the pure C++ library such as lacking C++11 std::to_string. However, the information about it lacking the C function overloads was new to me.
In practice the lacking overloads with g++ means
ignoring the g++ issue, or
avoiding using the missing g++ overloads,
e.g. using only double sin( double ), or
using the std namespace overloads
(one then needs to include <cmath> to guarantee their presence with g++).
In order to use the g++ std namespace overloads unqualified, one practical approach is to define headers wrappers for this compiler. I've used that approach to address g++ shortcomings wrt. to the printf family. For as David Wheeler once remarked, “All problems in computer science can be solved by another level of indirection”…
Then things can be arranged so that standard code that uses g++'s missing overloads, also compiles with g++. This adjusts the compiler to the standard, with a fixed amount of code.
Just like any other header file, you #include <cassert> when you use something declared in that header file, such as assert().
See an easily accessible reference
#include <iostream>
// uncomment to disable assert()
// #define NDEBUG
#include <cassert>
int main()
{
assert(2+2==4);
std::cout << "Execution continues past the first assert\n";
assert(2+2==5);
std::cout << "Execution continues past the second assert\n";
}
assert.h defines one macro function that can be used as a standard debugging tool.

Where are Library definitions located?

Could someone say me where I can found the source file where are the definitions of the standard libraries?
For example, where is the file string.c that contains the definitions of the function prototyped in string.h? And above all, it exists?
its all in compilled state, some of maybe optimized by asm. You need find sources of your compiler to see definitions
For GCC, which is open source, you can download the sources for the libstdc++ library from their mirror sites here. Included in the download is the source for the std library. Bear in mind that different vendors will have different implementations, so the link provided is merely how the developers of GCC decided to implement the standard library
You're probably not going to like this.
The C++ Standard does not say specifically where anything in the Standard Libraries are actually implemented. It says where things are declared, but only to the degree that it names the file(s) you must #include in order to bring the names in. For example, the Standard says that:
std::string
is a typedef for basic_string<...>, and in order to bring that typedef in to your program, you must #include <string>. It doesn't actually say that basic_string or string are defined in <string> however, and it doesn't say where, on your hard drive <string> is even located. In fact, it's often not in <string> in the real world. In my implementation, (MSVC10) string is defined in a different file, <xstring>, and it looks like this:
typedef basic_string<char, char_traits<char>, allocator<char> >
string;
Useful, huh?
There's another aspect. A lot of the stuff in the Standard Library is template stuff, like string, so because of the way templates work in C++ these facilities must be so-called "include libraries." But not everything in the Standard Library is made up of templates.
Consider sprintf. The Standard says that this declaration is provided by #include <cstdio> but that, like string isn't even where it's declared. And sprintf isn't a template thing. the implementation is in what's often called the CRT -- the C Runtime Library. This is a collection of DLLs and LIBs (in MSVC10, anyway) that your program links to to run code like sprintf.
Now the bad news is those components that are in the CRT are generally shipped without source code. You don't know where sprintf is implemented and you can't look at the source code. You're left with little alternative in these cases except get a job with MicroSoft so you can take a look at the source code. :)