// SomeOtherClass.hpp
#pragma once
int someOtherCallMe();
class SomeOtherClass {
public:
static int callMe() {
static int _instance = 7;
++_instance;
return _instance;
}
};
// SomeOtherClass.cpp
#include "SomeOtherClass.hpp"
int
someOtherCallMe() {
return SomeOtherClass::callMe();
}
// main.cpp
#include "SomeOtherClass.hpp"
#include <iostream>
int
main() {
std::cout << SomeOtherClass::callMe();
std::cout << someOtherCallMe();
return 0;
}
I have three files: SomeOtherClass.hpp/cpp, main.cpp. Those files result in two binaries: shared library (of SomeOtherClass.cpp) and executable(of main.cpp, linked with shared library).
Does C++ guaranties that static <any-type> _instance will be a single variable during the execution of a program (does not matter in how many binaries it was defined)?
Note
To clarify the situation. The confusion I see in this situation is that, on one hand, the SomeOtherClass::callMe is defined in program twice, that is expected (because class static member function are actually a regular function with internal linkage, if they are defined in place, like in this case), and that is what you can see from disassembly. Since we have two functions with static local variables in machine code. How does the language/standard qualify their behaviour?
Yes. A static will be a single value. A lot of other things are not well defined or are new to the standard. (When are they initialized if they are global? Is the code for static initialization within a function thread-safe?) But, yes, you can count on there being only one.
The only clarification here is outside the standard but of practical importance if you are creating a shared library (.so or .dll): You can't statically (privately) link your C++ class library into the shared library. Otherwise, that would make two copies if you do this within two different shared libraries. (This comment applies to everything about a library, not just static variables. If you do this, then there is duplication of everything.)
Edit: On many platforms (such as Linux and Windows), this can be used to purposefully "hide" your static variable. If you don't make your function/class accessible outside the dll/so (using declspec or a visibility attribute), then you can ensure your dll/so has its own copy of the entire class. This technique can help reduce unwanted interactions between libraries. However, in your case, it sounds like you really want only one, which will be the case if your class has proper visibility throughout all of your libraries (only visible in one, and other libraries link to that library).
Edit again to refer to the standard
If a function with external linkage is declared inline in one translation unit, it shall be declared inline in all translation units in which it appears; no diagnostic is required. An inline function with external linkage shall have the same address in all translation units. A static local variable in an extern inline function always refers to the same object.
7.1.2.4, C++14
Does C++ guaranties that static _instance will be a single variable during the execution of a program (does not matter in how many binaries it was defined)?
I don't think the language has anything to say about that. It does not talk about static libraries or dynamic libraries.
It's the responsibility of an implementation to provide the mechanism to make sure that it is possible to have one definition. It's up to a user to make sure that they use the mechanism provided by the implementation to have one definition of the static variable in the function.
Related
I have seen in stackoverflow that
//define in .h
inline void fun()
{
static int i; // one instance include in multiple cpp
}
static inline void fun1()
{
static int i; // multiple instance included in multiple cpp
}
I often write signleton in such a pattern
//define in .h
class Singleton
{
static Singleton& Instance()
{
static Singleton s;
return s;
}
private:
int i;
}
a lot of coders write in this way, Can someone explain is it correct, how C++ ensure one instance?
actually in the inline and static inline version, there is no clear cpp declaration to ensure single instance.
The C++ standard does not "ensure" anything.
The C++ standard specifies the observed results, what happens as the result of this declaration
It is up to each C++ compiler to implement this C++ specification in the manner that produces the specified results.
The C++ standard does not specify exactly how the compiler and the linker go about doing this. The low level details that produces these results are not specified or mandated by the C++ standard, in any way. This is entirely up to the compiler and the linker.
Having said that: the common approach is for the compiler to produce an instance of the static object in every compiled .cpp file. It is also tagged in some manner that uniquely identifies it; and indicates that, when linked with other translation units, only one instance of the uniquely-identified object (in all the compiled object files) is produced in the final linked executable.
This is a problem that was inherited from C and you have to go back quite a bit in history. So a long time a ago in a language not quite C++ ...
The inline keyword was just a hint to the compiler that you would like that function to get inlined. Now some compilers just ignored it because nothing said you had to inline functions marked inline. Some compilers addded a fudge factor to their automatic inline heuristic to make it more likely to get inlined. Others always inlined.
This then caused a problems for functions defined in headers because when the function was not actually inlined you ended up with the same function in multiple compilation units and then the linker complained.
Some compilers marked inline functions so that the linker would ignore duplicate definitions. But to be portable you had to mark your functions static inline. That way, even if the function is present in each compilation unit, the function isn't exported and doesn't collide with definitions of the same function in other compilation units. Drawback is that you get multiple copies of the same function, which is a problem when you have local static variables or use the address of the function.
Warp forward to the near present...
Compilers have gotten a lot smarter about inlining automatically and the feature to mark inline function to allow multiple defintions has kind of taken hold and that is the meaning of the inline specifier in C++. Since C++17 this also holds for inline variables, not just functions.
So inline causes the compiler to mark the function (or variable) in the object file for the linker to
Allow multiple definitions without error or warning.
Pick any one of the definitions and replace all the other instances with that one.
All duplicates of the inline function will end up with the same address and any local static variable will end up with a single instance too. All copies become the same object.
PS: using a static local variable for a singleton is imho the best way as it avoids the Static Initialization Order Fiasco as much as can be and is thread safe.
I have a set of pre defined C source code files that declares defines a lot of static functions - they are just coded up in .c files and not declared in any .h headers file.
Now I am trying to make use of those functions in my C++ application code:
Cmethods.c
static int amethod(int oppcheck)
{
}
A library is created using the C source code files:
$ nm --demangle userlib.a | grep amethod
00000000000001b6 t amethod
CppApp.h
extern "C" { int amethod(int oppcheck); }
CppApp.cpp
#include "CppApp.h"
voit callme()
{
amethod(check);
}
However during compilation ensuring that userlib.a is linked I get below error:
: undefined reference to `amethod'
$ nm --demangle userappcode.a | grep amethod
00000000000001b6 t amethod
U amethod
My further findings is that for functions in C source code files if declared in C header files - the linker error for them never occurs.
Note I cannot touch the C source code files - they are provided by third party community and we cannot break the license.
How can I resolve the issue
I have a set of pre defined C source code files that declares defines a lot of static functions.
Now I am trying to make use of those functions in my C++ application code:
Remove the static from those functions you want to call from some other translation unit.
If you cannot do that, you can't use these functions from outside. And the compiler could even optimize them to the point of removing them from your object file.
(a dirty trick that I do not recommend could be to compile that C code with gcc -Dstatic= to have the preprocessor replace static by nothing)
Note I cannot touch the C source code files.
Then your task is impossible.
You could "augment" the translation units, perhaps by appending to them a public (non static) function calling the static one. For example, you might compile something like
// include the original C code with only `static`
#include "Cmethods.c"
// code a public wrapper calling the static method
extern int public_amethod(int oppcheck);
int public_amethod(int oppcheck) { return amethod(oppcheck); }
Note I cannot touch the C source code files - they are provided by third party community and we cannot break the license -
It looks like you might not be legally allowed to compile that code, or that you cannot distribute its object file. There are no technical tricks to overcome a legal prohibition. If that goes in court, you'll probably lose!
Your issue is not technical, but social and legal. You may need a lawyer. You could also talk with the provider of the original code, and ask him if you are allowed to do what you want.
(without more motivation and context, your question looks weird)
static functions in C and static member functions in C++ are two different things. In C, a static function it is limited to its translation unit and invisible outside, this essential means object file(.o/.obj).
In C++, static can also apply to member functions and data members of classes. A static data member is also called a "class variable", while a non-static data member is an "instance variable".
If you defined amethod with static, then the function will have a internal linkage which means you can't link this function from other source files.
internal linkage.
The name can be referred to from all scopes in the
current translation unit. Any of the following names declared at
namespace scope have internal linkage
variables, functions, or function templates declared static
non-volatile non-inline (sinceC++17) const-qualified variables
(including constexpr) that aren'tdeclared extern and aren't previously
declared to have external linkage.
data members of anonymous unions
you might not touch the C source but a hacky solution is to #include it into a different translation unit with functions that forward the statics. This is not something I would recommend as a general answer but ...
file1.c:
static void function1(int)
{ ...}
file2.c:
#include "file1.c"
void fwd_function1(int x)
{
function1(x);
}
I am working on a factory that will have types added to them, however, if the class is not explicitly instiated in the .exe that is exectured (compile-time), then the type is not added to the factory. This is due to the fact that the static call is some how not being made. Does anyone have any suggestions on how to fix this? Below is five very small files that I am putting into a lib, then an .exe will call this lib. If there is any suggestions on how I can get this to work, or maybe a better design pattern, please let me know. Here is basically what I am looking for
1) A factory that can take in types
2) Auto registration to go in the classes .cpp file, any and all registration code should go in the class .cpp (for the example below, RandomClass.cpp) and no other files.
BaseClass.h : http://codepad.org/zGRZvIZf
RandomClass.h : http://codepad.org/rqIZ1atp
RandomClass.cpp : http://codepad.org/WqnQDWQd
TemplateFactory.h : http://codepad.org/94YfusgC
TemplateFactory.cpp : http://codepad.org/Hc2tSfzZ
When you are linking with a static library, you are in fact extracting from it the object files which provide symbols which are currently used but not defined. In the pattern that you are using, there is probably no undefined symbols provided by the object file which contains the static variable which triggers registration.
Solutions:
use explicit registration
have somehow an undefined symbol provided by the compilation unit
use the linker arguments to add your static variables as a undefined symbols
something useful, but this is often not natural
a dummy one, well it is not natural if it is provided by the main program, as a linker argument it main be easier than using the mangled name of the static variable
use a linker argument stating that all the objects of a library have to be included
dynamic libraries are fully imported, thus don't have that problem
As a general rule of thumb, an application do not include static or global variables from a library unless they are implicitly or explicitly used by the application.
There are hundred different ways this can be refactored. One method could be to place the static variable inside function, and make sure the function is called.
To expand on one of #AProgrammer's excellent suggestions, here is a portable way to guarantee the calling program will reference at least one symbol from the library.
In the library code declare a global function that returns an int.
int make_sure_compilation_unit_referenced() { return 0; }
Then in the header for the library declare a static variable that is initialized by calling the global function:
extern int make_sure_compilation_unit_referenced();
static int never_actually_used = make_sure_compilation_unit_referenced();
Every compilation unit that includes the header will have a static variable that needs to be initialized by calling a (useless) function in the library.
This is made a little cleaner if your library has its own namespace encapsulating both of the definitions, then there's less chance of name collisions between the bogus function in your library with other libraries, or of the static variable with other variables in the compilation unit(s) that include the header.
I am working on a factory that will have types added to them, however, if the class is not explicitly instiated in the .exe that is exectured (compile-time), then the type is not added to the factory. This is due to the fact that the static call is some how not being made. Does anyone have any suggestions on how to fix this? Below is five very small files that I am putting into a lib, then an .exe will call this lib. If there is any suggestions on how I can get this to work, or maybe a better design pattern, please let me know. Here is basically what I am looking for
1) A factory that can take in types
2) Auto registration to go in the classes .cpp file, any and all registration code should go in the class .cpp (for the example below, RandomClass.cpp) and no other files.
BaseClass.h : http://codepad.org/zGRZvIZf
RandomClass.h : http://codepad.org/rqIZ1atp
RandomClass.cpp : http://codepad.org/WqnQDWQd
TemplateFactory.h : http://codepad.org/94YfusgC
TemplateFactory.cpp : http://codepad.org/Hc2tSfzZ
When you are linking with a static library, you are in fact extracting from it the object files which provide symbols which are currently used but not defined. In the pattern that you are using, there is probably no undefined symbols provided by the object file which contains the static variable which triggers registration.
Solutions:
use explicit registration
have somehow an undefined symbol provided by the compilation unit
use the linker arguments to add your static variables as a undefined symbols
something useful, but this is often not natural
a dummy one, well it is not natural if it is provided by the main program, as a linker argument it main be easier than using the mangled name of the static variable
use a linker argument stating that all the objects of a library have to be included
dynamic libraries are fully imported, thus don't have that problem
As a general rule of thumb, an application do not include static or global variables from a library unless they are implicitly or explicitly used by the application.
There are hundred different ways this can be refactored. One method could be to place the static variable inside function, and make sure the function is called.
To expand on one of #AProgrammer's excellent suggestions, here is a portable way to guarantee the calling program will reference at least one symbol from the library.
In the library code declare a global function that returns an int.
int make_sure_compilation_unit_referenced() { return 0; }
Then in the header for the library declare a static variable that is initialized by calling the global function:
extern int make_sure_compilation_unit_referenced();
static int never_actually_used = make_sure_compilation_unit_referenced();
Every compilation unit that includes the header will have a static variable that needs to be initialized by calling a (useless) function in the library.
This is made a little cleaner if your library has its own namespace encapsulating both of the definitions, then there's less chance of name collisions between the bogus function in your library with other libraries, or of the static variable with other variables in the compilation unit(s) that include the header.
I am getting very confused in some concepts in c++. For ex: I have following two files
//file1.cpp
class test
{
static int s;
public:
test(){s++;}
};
static test t;
int test::s=5;
//file2.cpp
#include<iostream>
using namespace std;
class test
{
static int s;
public:
test(){s++;}
static int get()
{
return s;
}
};
static test t;
int main()
{
cout<<test::get()<<endl;
}
Now My question is :
1. How two files link successfully even if they have different class definitions?
2. Are the static member s of two classes related because I get output as 7.
Please explain this concept of statics.
They link because the linker knows almost nothing about the C++ language. However, if you do this, you have broken the One Definition Rule, and the behaviour of your program will be undefined. writing invalid code is not a good way of learning C++. Also, you seem to be having a lot of questions about static variables - the concept is really not all that complex - which C++ textbook are you using that does not explain it well?
The classes are (as far as the linker is concerned) identical. get() is just an inline function the linker never sees.
static in a class doesn't limit the member to file scope, but makes it global for all class instances.
[edit:] You'd get an linker error if you would put int test::s=5; into the second file as well.
Static is a strange beast in C++, that has different meanings depending on the context.
In File1.cpp, "static int s" in the class definition indicates that s is a static member, that is, is common to all instances of test.
The "static test t", though, has a different meaning: a static global variable only exists in the compilation unit, and will not be visible by other units. This is to avoid linker confusion if you were using the same name for two different things. In modern C++, one would use anonymous namespaces for this:
namespace
{
test t;
}
This means that t inside File1.cpp and t inside File2.cpp are separate objects.
In File2.cpp, you also defined a static method get: a static method is a method that belongs to the class instead of the instance, and that can only access static members of the class.
A last use of static, that you did not use in your example, is the local static variable. A local static variable is initialised the first time it gets executed, and keeps its value throughout the execution, a bit like a global variable with a local scope:
int add()
{
static value = 0;
value++;
return value;
}
Calling add() repetitively will return 1, then 2, then 3... This local static construct can be useful for local caches for example.
How two files link successfully even if they have different class definitions?
You violated the One Definition Rule (ODR) by defining the same class differently in different translation units. That invokes the dreaded Undefined Behavior. Which means the code is allows to do anything, including, but not limited to, doing what you wanted, formatting your hard disk, or causing an un-accounted for eclipse of the sun.
Note that compilers/linker are not requested to detect ODR violations.
Are the static member s of two classes related because I get output as 7.
Maybe they are, maybe they are not. Really, undefined behavior might do just anything. What you see is just an artifact of however your compiler and linker are implemented.
A likely implementation will happily link all references to test::s to the same instance, but let each translation unit have - and link to - their own t object. (Since the class has only inline functions, the linker most likely never even sees anything of test except for test::s and those t instances.)
Unnice side-effect of how C++ actually works. Use namespaces to make the class names different to outside.
In past I had used the quite burdensome in practice rule: every library and file has to have a private namespace for to avoid such link conflicts. Or put the utility classes right into the main class definition. Anyway: not to pollute global namespace and most importantly ensure uniqueness of names across the whole project. (Writing that now I notice that I used pretty much verbatim the concept from Java.)
My search for equivalent of C's static in C++ was unfruitful...