which compiling a multithreaded program we use gcc like below:
gcc -lpthread -D_REENTRANT -o someprogram someprogram.c
what exactly is the flag -D_REENTRANT doing over here?
Defining _REENTRANT causes the compiler to use thread safe (i.e. re-entrant) versions of several functions in the C library.
You can search your header files to see what happens when it's defined.
Excerpt from the libc 8.2 manual:
Macro: _REENTRANT
Macro: _THREAD_SAFE
These macros are obsolete. They have the same effect as defining
_POSIX_C_SOURCE with the value 199506L.
Some very old C libraries required one of these macros to be defined
for basic functionality (e.g. getchar) to be thread-safe.
We recommend you use _GNU_SOURCE in new programs. If you don’t specify
the ‘-ansi’ option to GCC, or other conformance options such as
-std=c99, and don’t define any of these macros explicitly, the effect is the same as defining _DEFAULT_SOURCE to 1.
When you define a feature test macro to request a larger class of
features, it is harmless to define in addition a feature test macro
for a subset of those features. For example, if you define
_POSIX_C_SOURCE, then defining _POSIX_SOURCE as well has no effect. Likewise, if you define _GNU_SOURCE, then defining either
_POSIX_SOURCE or _POSIX_C_SOURCE as well has no effect.
JayM replied:
Defining _REENTRANT causes the compiler to use thread safe (i.e. re-entrant) versions of several functions in the C library.
You can search your header files to see what happens when it's defined.
Since OP and I were both interested in the question, I decided to actually post the answer. :) The following things happen with _REENTRANT on Mac OS X 10.11.6:
<math.h> gains declarations for lgammaf_r, lgamma_r, and lgammal_r.
On Linux (Red Hat Enterprise Server 5.10), I see the following changes:
<unistd.h> gains a declaration for the POSIX 1995 function getlogin_r.
So it seems like _REENTRANT is mostly a no-op, these days. It might once have declared a lot of new functions, such as strtok_r; but these days those functions are mostly mandated by various decades-old standards (C99, POSIX 95, POSIX.1-2001, etc.) and so they're just always enabled.
I have no idea why the two systems I checked avoid declaring lgamma_r resp. getlogin_r when _REENTRANT is not #defined. My wild guess is that this is just historical cruft that nobody ever bothered to go through and clean up.
Of course my observations on these two systems might not generalize to all systems your code might ever encounter. You should definitely still pass -pthread to the compiler (or, less good but okay, -lpthread -D_REENTRANT) whenever your program requires pthreads.
In multithreaded programs, you tell the compiler that you need this feature by defining the _REENTRANT macro before any #include lines in your program. This does three things, and does them so elegantly that usually you don’t even need to know what was done:
Some functions get prototypes for a re-entrant safe equivalent.
These are normally the same function name, but with _r appended so
that, for example, gethostbyname is changed to gethostbyname_r.
Some stdio.h functions that are normally implemented as macros
become proper re-entrant safe functions.
The variable errno, from errno.h, is changed to call a function,
which can determine the real errno value in a multithread safe way.
Taken from Beginning Linux Programming
It simply defined _REENTRANT for the preprocessor. Somewhere in the associated code, you'll probably find #ifdef _REENTRANT or #if defined(_REENTRANT) in at least a few places.
Also note that the name "_REENTRANT: is in the implementer's name space (any name starting with an underscore followed by another underscore or a capital letter is), so defining it means you've stepped outside what the standard defines (at least the C or C++ standards).
Related
I have a C++ application running bare-metal that I want to make as small as possible.
I am not using dynamic memory allocation anywhere. I am using no STL functions. I've also overridden all the varieties of "delete" and "new" with empty functions. Nonetheless, when I look at a sorted list of symbols I see that malloc() is still one of the largest items in my compiled binary. I could shrink my binary by about 25% if I could get rid of it.
Do C++ runtimes generally require malloc() for behind-the-scenes type work?
(I'm using Xilinx's fork of gcc for the Microblaze architecture, if that matters)
Reliance of a program on malloc() can occur in both C and C++, even if the program doesn't directly use them. It is a quality of implementation matter for the compiler and standard library rather than a requirement by the standards.
This really depends on how the both the compiler startup code (code that sets things up so main() can be called) works and how standard library code is implemented.
In both C and C++, for example, startup code (in hosted environments) needs to collect information about command line arguments (possibly copy to some allocated buffer), connect to standard files/streams (like std::cout and std::cin in C++, and `stdout and stdin in C). Any of these things can involve dynamic memory allocation (e.g. for buffers associated with standard streams) or execute code that is not actually needed by the program.
C++ has two kinds of implementations, hosted and freestanding. Hosted implementations do assume that malloc is present and often do use it for internal purposes. Freestanding implementations assume that only the new function is present, because it supports the C++ keyword new, but it is easy to ensure that this function doesn't get called.
The difference between the two is that in a freestanding implementation, you can control program startup and the set of required headers and libraries is limited. Program startup is controlled by setting the entry point.
g++ -ffreestanding -e _entry program.cpp
program.cpp might be:
extern "C" int entry()
{
return 0;
}
The extern "C" is necessary to prevent C++ name mangling, which might make it difficult to figure out what the name of entry is during linking. Then, don't use new, std::string, stream I/O, STL, or the like, and avoid at_exit.
This should give you control over the startup and cleanup code and limit what the compiler can implicitly rely on being available from the standard library. Note, however, that this can be a challenging environment. Not only will you prevent initialization of heaps, I/O streams, and the like, but you will also prevent setup of exceptions, RTTI, and the calling of static storage object constructors, among other things. You will have to write code or use libraries to manually opt into several features of C++ you might want to use. If you go this route, you may want to peruse this wiki http://wiki.osdev.org/C%2B%2B. You may want to at least call global constructors, which is pretty easy to do.
Explanation
The standard
C++ has the notion of a "freestanding implementation", in which fewer headers are available.
3.6.1 Main function [basic.start.main]
1 [snip] It is implementation-defined whether a program in a freestanding environment is required to define a main function.
17.6.1.3 Freestanding implementations [compliance]
1 Two kinds of implementations are defined: hosted and freestanding (1.4). For a hosted implementation, this
International Standard describes the set of available headers.
2 A freestanding implementation has an implementation-defined set of headers. This set shall include at least
the headers shown in Table 16.
3 The supplied version of the header <cstdlib> shall declare at least the functions abort, atexit, at_quick_exit, exit, and quick_exit (18.5). [snip]
Table 16 lists ciso646, cstddef, cfloat, limits, climits, cstdint, cstdlib, new, typeinfo, exception, initializer_list, cstdalign, cstdarg, cstdbool, type_traits, and atomic.
Most of the above headers contain simple definitions of types, constants, and templates. The only ones that may seem problematic are typeinfo, exception, cstdlib, and new. The first two support RTTI and exceptions, respectively, which you can ensure are disabled with additional compiler flags. cstdlib and new you can simply ignore by not calling exit/at_exit and not using new expressions. The reason for avoiding at_exit is it might call new internally. Nothing else in the freestanding fragment should call call anything in cstdlib or new.
The options
The most important option above is -e _entry, which gives you control over what runs when your program starts.
-ffreestanding tells the compiler and the standard library (rather, its freestanding fragment) not to assume that the entire standard library is present (even if it still is). It may prevent the generation of surprising code. Note that this option doesn't actually restrict which headers are available to you. You can still use iostream, for instance, though it may be a bad idea if you also changed the entry point. What it does is it prevents the code supporting the freestanding headers from calling anything outside the freestanding headers, and prevents the compiler from generating any such calls implicitly.
If you use any STL like std::lib or std::map. Or even std::cout, there will be dynamic memory allocations behind the scene.
It will always need malloc. Because the binary has to be loaded and also the shared libraries.
I'm reading a piece of code that seems like it optionally uses the C++ Boost library. It is as follows:
#ifdef _HAVE_BOOST
#include <boost/random.hpp>
#endif
Later on in the code, there are several statements that depend on this "_HAVE_BOOST". I presume that _HAVE_BOOST is simply a flag that is set to true, if the C++ library is properly imported.
Is the "_HAVE_BOOST" flag a built-in part of C++ ifdef syntax? That is, I tried Googling for this flag but didn't find any documentation. Also, at the head of the file, no #include<boost> is present. It looks like this boost functionality is deprecated throughout the file -- would _HAVE_BOOST be set to true if this #include<boost> were added?
Is there a list or documentation somewhere for describing the kinds of capital letters that go along with #ifdef?
I presume that _HAVE_BOOST is simply a flag that is set to true...
#ifdef _HAVE_BOOST does not test whether _HAVE_BOOST is true; It test whether such preprocessor macro is defined at all, regardless of the value.
...if the C++ library is properly imported.
Yes, considering the context, this particular macro is probably meant to signify, whether Boost is available or not and thus, whether it's possible to depend on it.
Is there a list or documentation somewhere for describing the kinds of capital letters that go along with #ifdef?
Macros can be defined with either #define directive in a header file or, in the compilation command (See the -D option for gcc for example). Compilers may also predefine some macros as well.
Any header file can define macros. You should usually be able to find which macros may be defined by reading the documentation, or if you don't have documentation, by reading the header files themselves.
would _HAVE_BOOST be set to true if this #include were added?
I find it unlikely that it would be defined in <boost> itself. After all, testing if Boost is available after you try to include it would be rather pointless.
When is _HAVE_BOOST defined?
You should ask that from the person who wrote the code. Another question to ponder is, is it defined at all? If it isn't, then the code between the ifdefs is removed by the preprocessor.
My crystal ball tells me that it's probably supposed to be defined by some sort of configuration script for the build process. For example, autoconf has a macro that will define a preprocessor macro HAVE_header-file if a header exists. Note the lack of underscore at the beginning.
this just means that if you define a preprocessor macro "_HAVE_BOOST" the compiler will include boost/random.hpp. Like this:
#define _HAVE_BOOST
#ifdef _HAVE_BOOST
#include <boost/random.hpp>
#endif
Look here for more details about preprocessor directives.
If the compiler supports c++11, it will have <random> support.
With some clever use of indirect includes and typedefs (or using statements ?!) it could be made to work with or without boost for random.
I have two versions of a c++ compiler installed on my computer. One of them recognizes the __COUNTER__ macro and the other does not. After doing some research to make the program compile in both I have yet to come across the Macro definition for __COUNTER__. Is this some special Macro done by the compiler or can I copy the definition for __COUNTER__ into my source code, if I can copy it what is the code I need.
__COUNTER__ is a built-in in several common compilers. It is not possible to define manually. If you're stuck with a compiler that doesn't support it, your best option might be to run your code through a preprocessor that does support it before feeding it into the compiler.
It's a special macro which has been introduced by Visual Studio and I think is now supported by GCC too.
It basically provides a unique counter over integral numbers which can be used to generate unique identifiers.
From GCC release notes:
A new predefined macro __COUNTER__ has been added. It expands to sequential integral values starting from 0. In conjunction with the ## operator, this provides a convenient means to generate unique identifiers.
If you don't have it available to a compiler you can easily mimic the behavior with a static variable. But I'm not sure what you are compiling so I'm not sure how this counter is used in the code you have available.
When we look at STL header files, we see many macros used where we could instead write single lines, or sometimes single word, directly. I don't understand why people use so many macros. e.g.
_STD_BEGIN
using ::type_info;
_STD_END
#if defined(__cplusplus)
#define _STD_BEGIN namespace std {
#define _STD_END }
#define _STD ::std::
Library providers have to cope with a wide range of implementations and use case. I can see two reasons for use of macros in this case (and there are probably others I'm not thinking about now):
the need to support compilers which don't support namespace. I'm not sure if it would be a concern for a recent implementation, but most of them have a long history and removing such macros even if compilers which don't support namespaces are no more supported (the not protected using ::type_info; hints that it is the case) would have a low priority.
the desire to allow customers to use their implementation of the standard library in addition to the one provided by the compiler provider without replacing it. Configuring of the library would then allow to substitute another name for std.
That
#if defined(__cplusplus)
in your sample is the key. Further down in your source I would expect to see alternative definitions for the macros. Depending on compilation environment, some constructs may require different syntax or not be supported at all; so we write code once, using macros for such constructs, and arrange for the macros to be defined appropriately depending on what is supported.
Macros vs variables : macros can run faster in this case because they are actually made constants after pre-processing.(Operations on constants are faster than that on variables).
Macros vs functions : Using macros avoids the overhead compared to that when using functions requires pushing parameters to stack, pushing return address and then popping from stack....
Macros : Faster execution but requires more memory space.
Function : Slower execution but less memory space.
I'm trying to move a project from an old linux platform to a kubunutu 9.04. Now I get this error when compiling with gcc 4.3.3:
/usr/src/linux-headers-2.6.28-11-generic/include/linux/cpumask.h:600:37: error: "and" may not appear in macro parameter list
If I understand the message right, it is not allowed to use "and" as a macro parameter, since it is a "reserved command". Two questions about that:
How is this possible? I cannot imagine that there is such a mistake in the linux header files... Did I do something wrong before? I tried an #undef and but this won't help.
How do I fix this error? It cannot be true that I have to change the linux header files, can it?
Thanks for help.
I believe the problem is that and is a keyword in C++ but not C (they use &&).
The kernel guys sometimes macros as an alternative to inline functions. Sometimes, however, they need macros because what they want to do has to be done in the scope of the calling function, and defining a function to do that won't work (for instance a macro to find out the name of the current function).
Assuming the macros in question are really fake inlined functions, it would be possible to write your own .c file full of nothing but functions calling these macros, compile it, and refer to those functions via an extern "C" header. You would get the same behavior, but slightly worse performance (which is unlikely to be a problem).
If the macros actually have to be macros, then your best bet is to hand edit them to be C++ compliant.
The linux headers are C headers, not C++.
define for_each_cpu_and(cpu, mask, and) на #define for_each_cpu_and(cpu, mask, and_deb)
Found this solution # http://www.linux.org.ru/forum/development/4797542
It would help if you also showed the line in question. Perhaps it's all down to context, if you do something crazy before including the header, the compiler might be confused and generate a non-obvious error message.
There are cases when "and" is indeed a reserved word, and if it's C++-only the kernel developers won't care too much since the kernel is focused on C.