Segment fault occurs depend on cpp sequence in gcc compile command? - c++

I write a simple program that adds a value into a global set container when a new class (eg: One,Two) is defined:
GlobalSet.h
#include <set>
struct GlobalSet{
public:
static void* addValue(int val);
private:
static std::set<int> s;
};
GlobalSet.cpp
#include "GlobalSet.cpp"
std::set<int> GlobalSet::s;
void* GlobalSet::addValue(int val){
s.insert(val);
return NULL;
}
One.h
struct One{};
One.cpp
#include "One.h"
#include "GlobalSet.h"
void* globalset =GlobalSet::addValue(1);
Two.h
struct Two{};
Two.cpp
#include "Two.h"
#include "GlobalSet.h"
void* globalset2 =GlobalSet::addValue(2);
test.cpp
int main(){
return 0;
}
But this program will cause segment fault depend on cpp sequence in gcc compile command:
g++ GlobalSet.cpp One.cpp Two.cpp test.cpp -o test.exe //normal
g++ One.cpp Two.cpp GlobalSet.cpp test.cpp -o test.exe //segment fault!!
Why would it happen? How to fix the problem so that it works without care the sequence of cpp in gcc compilation?

Welcome to the Static Initialization Order Fiasco.
The C++ standard does not guarantee the initialization order of global objects in multiple translation units.
Depending on your link order, your code will attempt to construct globalset2 first. However, this calls a static class method addValue(), which attempts to access a std::set that has not been constructed, yet.
Undefined behavior, and a crash.
To fix this, go to www.google.com, search for "static initialization order fiasco", and keep reading, until you understand the issue. Once you do, you will know what to do to fix it, in your code.

Related

undefined reference error for static class member when it is defined in .cpp file

This question may seem similar to other "undefined reference error when accessing static class member" questions. I have explored them and what I understood is I need to define the static class member separately in a source file, so that an object is created for the static class member that holds data.
My problem is that I am following definition rules but still get the undefined reference errors.
problem can be reproduced using this code:
main.cpp
#include <iostream>
#include "src/a.hpp"
int main() {
std::cout << a::x;
return 0;
}
src/a.hpp
class a {
public:
static int x;
};
src/a.cpp
#include "a.hpp"
int a::x = 20;
I compile main.cpp using g++ main.cpp -o main. I have a test directory that has main.cpp and a sub directory src, src contains a.hpp and a.cpp.
The error resolves if i define the static variable within the header file, but other posts suggest it should lead to linker errors.
The problem was in the compile command I used, g++ main.cpp -o main does not compile src/a.cpp. Compile it with g++ main.cpp src/a.cpp -o main and it works fine.

Why is non-empty initialized static member std::string empty (in shared lib)?

Following is a simplification of code from a larger project:
// foo.h
#ifndef FOO_H
#define FOO_H
#include <string>
class Foo
{
public:
Foo( const std::string& s = magic_ );
void func();
static const std::string magic_;
private:
std::string s_;
};
void func( const std::string& s = Foo::magic_ );
#endif
//foo.cpp
#include "foo.h"
#include <iostream
const std::string Foo::magic_ = "please";
Foo::Foo( const std::string& s )
: s_( s )
{ }
void Foo::func() { std::cout << "[" << s_ << "]" << std::endl; }
void func( const std::string& s )
{
Foo( s ).func();
}
// main.cpp
#include "foo.h"
int main( int argc, char* argv[] )
{
func();
return 0;
}
I'll call the above a MCE, not a MCVE because unfortunately I've not been able to reproduce the problem in a simplification, which I can only guess is because of quirks of static variables and shared linkage - possibly an incorrect assessment, because of a not-thorough understanding of what's involved. But I will try to explain the problem. The following aspects of the above MCE are representative of the problem code:
A header file declares a class with a static member std::string.
The same header defines a function with an in-arg defaulted to the class' static member variable.
The header's corresponding source file defines the static member and function.
The translation unit is compiled to a shared library.
The executable's object code is linked with the shared library.
Compilation/output:
$ g++ -O3 -c -fPIC -o ./foo.o ./foo.cpp
$ g++ -O3 -shared ./foo.o -o ./libfoo.so
$ g++ -O3 -c -fPIE -o ./main.o ./main.cpp
$ g++ -O3 ./main.o -o ./a.out -L./ -lfoo
$ LD_LIBRARY_PATH=$LD_LIBRARY_PATH: ./a.out
[please]
Though not demonstrated above, is it a possibility that during executing the output may be "[]"? I.e. might Foo::magic_ be empty at the time used as the default value assigned to void func()'s in-arg?
This is hard to articulate in the absence of a demonstrable problem with the above MCE, but assuming it is truly representative of the problem code, I observe (by stdout due to gdb absence in the real build/test environment) that in void func(), in-arg s is an empty string - can anyone account for/explain why this could be?
I know initialization of static variables is not guaranteed across translation units - is that possibly involved here? (It seems like it might explain why the problem is not reproducible in an attempted simplification)
Again, apologies for the lack of a MCVE - I tried my best to create one.

Singleton across compilation units: linking library vs linking objects

I apologize if the title is not fully self-explanatory. I'm trying to understand why my singleton factory pattern is not working properly, and I ran into a bizarre difference when using library vs linking single objects files.
Here's a simplified version of the code:
main.cpp
#include <iostream>
#include "bar.hpp"
int main (int /*argc*/, char** /*argv*/)
{
A::get().print();
return 0;
}
bar.hpp
#ifndef BAR_HPP
#define BAR_HPP
#include <iostream>
class A
{
public:
static A& get ()
{
static A a;
return a;
}
bool set(const int i)
{
m_i = i;
print();
return true;
}
void print ()
{
std::cout << "print: " << m_i << "\n";
}
private:
int m_i;
A () : m_i(0) {}
};
#endif // BAR_HPP
baz.hpp
#ifndef BAZ_HPP
#define BAZ_HPP
#include "bar.hpp"
namespace
{
static bool check = A::get().set(2);
}
#endif // BAZ_HPP
baz.cpp
#include "baz.hpp"
Now, I build my "project" in two ways:
Makefile:
all:
g++ -std=c++11 -c baz.cpp
g++ -std=c++11 -o test main.cpp baz.o
lib:
g++ -std=c++11 -c baz.cpp
ar rvs mylib.a baz.o
g++ -std=c++11 -o test main.cpp mylib.a
Here are the outputs I get:
$ make all
$ ./test
print: 2
print: 2
$ make lib
$ ./test
print: 0
In the first case the call to A::get().set(2) in baz.hpp takes place, and the same instantiation of A is then used in the main function, which therefore prints 2. In the second case, the call to A::get().set(2) in baz.hpp never takes place, and in the main function the value set by the constructor (that is, 0) is printed.
So finally I can ask my question: why is the behavior different in the two cases? I would expect that either both print 0 once or print 2 twice. I always assumed that a library was just a compact way to ship object files, and that the behavior of linking mylib.a should be the same as that of linking baz.o directly. Why isn't that the case?
Edit: the reason, as explained by Richard, is that no symbols defined in baz.cpp are required in main.cpp, so baz.o is not extracted from the library and linked. This raises another question: is there a workaround to ensure that the instruction A::get().set(2) is executed? I would like to avoid making the singleton a global object, but I'm not sure it's possible. I would also like to avoid to include baz.hpp in the main, since there may be many bazxyz.hpp and that would require main.cpp to know in advance all of them, defying the whole purpose of the factory-like registration process...
If this is to be a static library, then some module somewhere is going to have to address something in each implementation file of the objects that are going to register themselves with the factory.
A reasonable place for this would be in bar.cpp (which is a file you don't yet have). It would contain some or all of the implementation of A plus some means of calling the registration functions the widgets you're going to create.
Self-discovery only works if the object files are linked into the executable. This gives the c++ startup sequence a chance to know about and construct all objects with global linkage.

Both static variables and global variables show different addresses in dynamic library and static library on Linux?

I have encountered on CentOS 6.5. As I have searched online that static variable behaves differently on Windows and on Linux when using dynamic library. That is, Windows would cause duplication of variables and Linux would not, like this one:
http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html
However, when I wrote a small program to validate this, I found that Linux also causes duplication. Here is my small program, including four files:
(1) A.h
#ifndef A_H
#define A_H
#include <cstdio>
static int b;
extern "C" class A {
public:
int mem;
A() {
printf("A's address: %p\n", this);
printf("B's address: %p\n", &b);
}
void print() {
printf("%p: %d\n", this, mem);
}
~A() {
printf("DELETE A!!!!! %p\n", this);
}
};
extern A a;
#endif
(2) A.cpp
#include "A.h"
A a;
(3) d.cpp
#include "A.h"
extern "C" void exec() {
a.print();
}
(4) main.cpp
#include "A.h"
#include <dlfcn.h>
typedef void (*fptr) ();
int main() {
a.mem = 22;
a.print();
void *handle;
handle = dlopen("d.so", RTLD_LAZY);
fptr exec = reinterpret_cast<fptr>(dlsym(handle, "exec"));
(*exec)();
dlclose(handle);
return 0;
}
Here is how I compile and run my program:
g++ d.cpp A.cpp -shared -rdynamic -o d.so -ldl -I. -fPIC -g -std=c++1y
g++ main.cpp A.cpp -ldl -I. -g -std=c++1y
./a.out
Both the dynamic part d.cpp and the static part main.cpp use the variables a and b declared in A.cpp and A.h. And here is the result of the program on my machine:
A's address: 0x600f8c
B's address: 0x600f90
0x600f8c: 22
A's address: 0x7fb8fe859e4c
B's address: 0x7fb8fe859e50
0x7fb8fe859e4c: 0
DELETE A!!!!! 0x7fb8fe859e4c
DELETE A!!!!! 0x600f8c
This surprises me a lot, because the addresses of global variable a and static variable b should be the same in the dynamic part and the static part. And it seems that modification on a in static part does not effect the a in dynamic part. Would anyone please answer my question, or help find out some mistakes in the program (if any)?
By the way, to be honest, on another project I am working on, I find that addresses of global variables are the same in dynamic library and in static library. But that project is too big and I cannot provide a small program to reproduce the behavior.
Thanks a lot !
The first command you showed builds a shared object d.so. Based on the context of your question, I surmise that you also intended to link with d.so, but your second command seems to be missing that part. I'm assuming that it's a typo, as this is the only explanation for the program output you showed -- that A.cpp is both linked to directly, and is also built into your d.so library.
Given that, quoting from the article you linked:
Object code routines used by both should not be duplicated in each.
This is especially true for code which use static variables such as
singleton classes. A static variable is global and thus can only be
represented once. Including it twice will provide unexpected results.
But that's exactly the rule you seem to be breaking, you're representing the statically-scoped instance of the A class twice, in your d.so, and in your main application executable.
So, that seems to be the indicated outcome: "unexpected results".

undefined reference to; class public function not accessible at link time

I'm trying to build a simple program where I defined a class and included it's header in Main. While linking, Linker complains about accessing any of the member function from class:
: undefined reference to voxel::anyFunction
even though functions are public and headers are included.
Originally I discovered the problem when creating an object of voxel - I had overloaded the default constructor, but I figure out the problem is present for any function from voxel class.
Here are some code excerpts:
voxel.hpp
class voxel
{
public:
//here defined some member variables
//ommited the constructor
void fillMemberValuesWithDummy();//sets all members to some dummy value
};
voxel.cpp
#include "voxel.hpp"
void voxel::fillMemberValuesWithDummy()
{
//does the assignment to member variables
}
Main.cpp
#include <iostream>
#include <fstream>
using namespace std;
#include "voxel.hpp"
{
voxel someVoxel;
somevoxel.fillMemberValuesWithDummy();
}
I figure it is something very stupid I am (not) doing here, but can you tell me what?
You need to link all object files to get the executable. When you have just your two source files you can compile them directly:
g++ -o myprog.exe Main.cpp voxel.cpp
When you want to divide compile and link and do it this way:
g++ -c -o Main.o Main.cpp
g++ -c -o voxel.o voxel.cpp
g++ -o myprog.exe Main.o voxel.o
Feel free to create an appropriate Makefile that generates such commands.
Remove the .exe if you OS doesn't need it.