Removing Unused (Unreferenced) Static Global Variable Constants in C++ - c++

Update,
I tried removing the static modifier, and I tried putting them in a namespace (as well as both of those), and none worked.
Hi,
I have a header file with common constants like names and stuff that are automatically included in each project (an example follows). The thing is that they are included in the compiled binary (EXE) whether they are used (referenced) or not. If I use DEFINEs instead, then naturally they are not included if they are not used, but of course consts are better than defines so… I tried Googling it, but the closest thing I could find was a question right here on SO that did not quite help. Matters of i18n aside, how can I keep the ones that are not used out of the binary, while still keeping it easy to use like this?
Thanks.
//COMMON.H:
static const CString s_Company _T("Acme inc.");
//etc. others
static const CString s_Digits _T("0123456789");
//TEST.CPP:
#include common.h
int main() {
AfxMessageBox(s_Company);
}
//s_Company should be in the final EXE, but s_Digits should not be, but is

The reason they're not stripped from the binary is because they are used: CString is not a POD type, so when you create instances of them at global scope, the compiler has to generate code to call their constructors and destructors.
If you want unused symbols to be stripped, just replace the CStrings with a POD type such as const TCHAR*:
static const TCHAR *s_Company = _T("Acme inc.");
static const TCHAR *s_Digits = _T("0123456789");
Then, the unused constants will be stripped from your binary automatically by the compiler. However, one important thing to keep in mind is that if your strings are used in multiple files, then your binary will have multiple copies of those strings in it, one copy for each translation unit that uses the string. Not even gcc's -fmerge-constants option seems to fix this. If you don't want this to happen, you'll need to use extern declarations in your header files and then put the string constants' values in source files (usually in one file, but that's not required). This also allows you to change the constants without needing to recompile every file that uses them.

If you don't need the values as literals, you can declare them in the header file as:
extern const CString s_Company;
Put each one of them in its own source file that defines it as:
const CString s_Company _T("Acme inc.");
Then you can only link in the constants that you need; the linker will tell you in its error messages if you're missing any! (There are also ways to tell the compiler to not make those symbols public in the built library – assuming you're building a library at all – but they're not standard or portable.)

If there are clear rules defined that make it clear when you want to use what, then you can use preprocessor defines like this:
#if defined CONFIG_COMPANY
static const CString s_Company _T("Acme inc.");
#elif defined CONFIG_DIGITS
static const CString s_Digits _T("0123456789");
#endif
You can then define or not define either of these values in a separate configuration header.
By the way, if this file is meant to be included in many source files, then you should probably refrain from declaring these constants as static. They have internal linkage and you'll get a separate copy of them in all of your translation units.

On Windows, especially using MFC, the answer is to put the strings into resources, and load the string from there using LoadResource / LoadString (see http://msdn.microsoft.com/en-us/library/a44fb3wy(VS.80).aspx)
In your case, you have two constant CStrings, So the resource compier will generate something like
#define IDS_COMPANY 1
#define IDS_DIGITS 2
So in this case you would have a .dll with two strings. You app would load the .dll (AfxLoadLibrary). Then when you need the string your app loads it from the resource .dll.
This is what keeps Windows apps from bloating with global static strings, bitmaps, etc.

Related

What does adding a pre-processor variable before a function declaration means?

I'm reading the Dear ImGui API, and i'm wondering what does it mean to add a pre-processor variable (here IMGUI_API) before the function declaration like this :
#ifndef IMGUI_API
#define IMGUI_API
#endif
...
namespace ImGui
{
...
IMGUI_API float GetWindowWidth();
...
};
Thanks in advance !
Like Hans Passant said - it won't always be empty.
One of the main properties of dynamic shared objects (and DLLs in Windows) is that the internal symbols of the library are not exposed to the user. In GCC, this is done by specifying the default symbol visibility to "hidden" on the command line when building the library. However, this has the undesirable effect of making all symbols, including the ones you want users to call, hidden, which makes your library effectively useless.
GCC provides a way to manually control visibility - __attribute__((visibility("default"))). This marks a function as having default visibility, meaning it will be exposed by the DSO. This attribute is specified before the function declaration.
This creates a new problem - the users of your library don't need/want this attribute specified on your library functions when they include your header file. When your header is included by the user, these definitions should be removed, leaving just a bare function declaration.
There's two ways to solve this - have two copies of your header, or use the preprocessor to change the code before compilation. Most (almost all) library programmers choose the latter, as keeping two copies of the same file synced is very difficult.
The way the writers of ImGui have implemented the latter option is rather elegant - rather than defining their API marker inline, like so:
#ifdef IMGUI_API_BUILD
#define IMGUI_API __attribute__((visibility("default")))
#else
#define IMGUI_API
#endif
They've defined it as follows:
#ifndef IMGUI_API
#define IMGUI_API
#endif
This has the effect of defining the symbol to a default value if it hasn't been overridden.
The genius of this is actually in the compilation process - by specifying the definition of IMGUI_API on the command line, they can change the behavior of the code without exposing elements of their build process to the world.
All they have to do is add -D IMGUI_API=__attribute((visibility("default"))) to the compiler command line and the header file magically marks every API function as being exported from the shared object.
In fact, they can change the definition to any value they want without exposing that detail in the header file used by other programmers in this way. Debug information, additional function options, specifying hot/cold path info... all of this can be specified on the command line without needing to place that information into the header file.
Edit:
Looking through their code now, it seems they haven't realized this, and have created a very powerful shared-library solution for Linux without meaning to. Despite that, all of the above is still valid - other libraries can do the same thing.

Reduce recompilation when editing global variables

I am working on a game,
I have a huge list of const global variables .h file which many .cpp file relies on.
(Enemies would like to know the max hp of players etc)
However, this is a compilation nightmare when any variable is changed in the file for game balancing.
I would like to prevent splitting up the files into multiple headers for the ease of the guy in charge of game balancing.
However, recategorizing is kind of a pain (clarity vs compile time, Player's maximum hp is used in many .cpp but it should belong to the PlayerVariables.h, including it in every file that uses it kind of destroys the purpose of splitting them up).
Is there a way to save some time other than the method above?
Just declare the global variables in the header file. And define them in another source file. That way if any of the values are changed only the globals.cpp needs to be recompiled since everything includes globals from the hpp.
In globals.hpp:
extern const unsigned PLAYER_MAX_HEALTH;
In globals.cpp:
#include "globals.hpp"
const unsigned PLAYER_MAX_HEALTH = 100;
You could try adding a configure-step with the preprocessor:
Only have preprocessor #defines in the config.h
Split it with the preprocessor into multiple headers only pulling in those definitions they need to declare actual const variables / enum-values / whatever.
Only copy those files which are different from the previous run over the previous version.
Optionally also have a glabals.cpp defining those symbols which might also need a definition.
Make sure to (re-)run make after the configuration was updated.
The advantage over just declaring external constant variables and defining and initializing them in a different translation-unit is constant-propagation and having proper compile-time-constants.

How does includes work in C++?

In my folder I have a small version.cpp file with the following structure:
#include "thelibr/version.h"
const int major = MAJOR;
const int minor = MINOR;
I cannot understand what this code does and how is it used by the remaining part of the code (stored in other files of the same directory).
First, I understand that the code sets values of two variables (major and minor) but what is not clear to me is where the values of MAJOR and MINOR are set. Are they set in thelibr/version.h.
Second, it is also not clear to me when the above given lines of the code are executed. They are not put in any method that could potentially be called from other methods coded in other files. So, how these lines can be called?
Third, I see that string version is not present in any other file from the same directory. Does it mean that none of these file uses the code stored in the version.cpp. Shouldn't we include version.h file somewhere in other file to be able to use the code from the version.cpp?
Fourth, if we set the values of major and minor variables in the version.cpp, will these variables be visible somewhere else? It wonders me since we do not use any words like global or external.
C++ doesn't have a module system like Python where pure symbols may be exported and their values used in another source file. Instead it has header files: The contents of thelibr/version.h are essentially copy-pasted in place of the #include line. Anything inside that file is processed as if it were written out in the version.cpp file.
To export from one file to another (or to create libraries which can be interpreted by the linker or dynamic loader), use extern storage, which is the default for many things.
Deciding what is visible from one .cpp file to the next is rather complicated, but as a rule you cannot share compile-time values such as the version number; you can only share access to runtime objects such as the ints which store the version number.
To use major and minor from another .cpp file, you could declare in version.h:
extern const int major;
extern const int minor;
And then #include "thelibr/version.h" from the other file.

Define global variable as hash

I have a number of C++ classes, alot of them (not all) share two "static size variables" e.g.
share.h
/*Other variables in this header used by all classes*/
static size width=10;//Used by about 60%
static size height = 12;//used by about 60%
So I placed them in a header file along with other objects that all classes share.
when I compile the project I get alot of warnings (from the classes which dont use these), which complain about them being defined and not used. But I need them there!
So I ask, is there a way to hash these to prevent such warnings?
Hashing them so that they can be defined! preventing warnings from classes calling this header file which dont require these last two variables, but they call header because they need everything else init
You should place them in an individual header file. So you can include it only in the classes they need it. This avoids the warning in the other classes. So in the end you will have two header files. One where the stuff for all classes is included and another where the variables which are not used in all are defined.
However try to avoid global variables.
Edit reading tune2fs' answer, I realized I may have interpreted the question wrong.
Perhaps you forgot to use extern in the header file? If you just include static definitions in the header file all compilation units will have unique copies, not shared. See also this explanation of static/extern
Edit Disambiguated in comments
static SomeClass NotUnusedInstance;
static void unused_vars_helper()
{
static SomeClass* take_address = &NotUnusedInstance;
}
This approach is design to have minimal impact (not invoking any actual code; take_address isn't actually initialized unless you call unused_vars_helper).
This should work pretty well for your case. You can make unused_vars_helper() static and/or move it inside an anonymous namespace to prevent external visibility of the helper.

c++ global constants issue

We have these set of "utility" constants defined in a series of file. The problem arises from the fact that TOO MANY files include these global constant files, that, if we add a constant to one of those files and try to build, it builds the whole entire library, which takes up more than an hour.
Could anyone suggest a better way for this approach? That would be greatly appreciated.
First, if you are defining them directly in the header, I'd suggest instead delcaring them extern const, and then defining them in a cpp file:
//in .hpp:
extern const std::string foo;
//in .cpp:
const std::string foo = "FOO";
That way, at least definitions can be changed without a rebuild.
Second, examine where they are being included. If the constant file is being included in a low level header, can the include be moved to the cpp instead? Removing it might lower the coupling so it doesn't have to rebuild as much.
Third, break up that file. I'd suggest mapping out a structure you'd eventually want, start adding new constants to the new structure instead of the old file. Eventually (when you are sure you've got the structure you want), refactor the old file into the new structure, and make the old file include the entire structure. Finally, go through and remove all includes of the old file, pointing them at the appropriate new sections. That'll break up the refactoring so you don't have to do it all at once.
And fourth, you might be able to trick your compiler into not rebuilding if the header file changes. You'd have to check your compiler's documentation, and it might be unsafe, so you'd occasionally want to add full builds as well.
Do you really need every global define to be included in every file? You should probably split the constants up into categories and then split them into different files.
Every .h that is included is simply copied at that point in the file that is including it. If you change something in a file (either directly or via changing something that is included) then it absolutely needs to be recompile.
Another solution would be to have a .h file that has an accessor to a map of string name/values. Then in the .cpp file of that map/accessor you can insert the new values. Every new value you put would only need 1 file to be recompiled.
Another solution is not to include the header file anywhere. Simply extern in the variables you need in each .cpp file.
Perhaps it's time to do some refactoring to improve the cohesion and reduce the coupling in your software design. Splitting the global constant files would allow modules to be more selective about which constants need to be included, which will eliminate some of the
unnecessary coupling. In the extreme case, you could break it all the way down to one constant per file, and ensure that each module only includes the constants it needs to use.
But that could result in poor cohesion, in the sense that the constants might naturally fall into related groups, such that a module that requires one constant will generally also
require many others from that group. So the trick is to find a better grouping of constants in the various global files, then ensure that each module only includes what it needs.
(Edit: I didn't think of external constants. Indeed, my idea is kinda stupid.)
(Edit: My "stupid" macro idea actually saves build time for when constants are added. Thanks for pointing that out, Brian!)
Use parallel building :-)
Seriously, I think one solution would be to create another header called utility_ex.hpp or something where you add new constants that you occasionally merge into utility.hpp (or whatever your current utility constants header is called).
Another (less efficient) solution would be to have a macro like this:
#define constant(name) get_constant(#name)
// # means turn name into a string literal
int get_constant(const char *name);
Now suppose you want MAX_CUSTOMERS to be defined as 100. You can say:
constant(MAX_CUSTOMERS)
in the code. In get_constant's code, you might have:
int get_constant(const char *name) {
if (!strcmp(name, "MAX_CUSTOMERS"))
return 100;
//shouldn't happen
return -1;
}