Linking error in dereferencing static variable - c++

(I've failed to find any similar question... so, I hope you can help me)
In a program in C++ that I'm developing, I have a class that simulates a thread. I'll call it "Test" here. In it, I have an static map (std::map, from STL) that in which I store some semaphores (because I need all of the threads to have access to the same semaphores). (I think it is not worth to explain why I'm using a map, instead of a vector, but I believe this shouldn't be a problem)
To "get" this static variable, I created a getMutexHash() function, that returns a pointer to the static map. But, for some reason, after compiling, I'm getting a linker error when trying to return a this pointer.
The following code exemplifies the problem:
// MAIN.CPP
#include "Test.h"
int main ()
{
Test test;
map<int, pthread_mutex_t>* mutexHash = test.getMutexHash();
return 0;
}
// TEST.H
#include <map>
#include <pthread.h>
using namespace std;
class Test
{
public:
map<int, pthread_mutex_t>* getMutexHash();
private:
static map<int, pthread_mutex_t> mutexHash;
};
// TEST.CPP
#include "Test.h"
map<int, pthread_mutex_t>* Test::getMutexHash()
{
return &mutexHash;
}
When compiling, I get no error nor warnings; but when linking, I receive this error:
Test.o: In function `Test::getMutexHash()':
Test.cpp:(.text+0x9): undefined reference to `Test::mutexHash'
collect2: ld returned 1 exit status
Can someone help me?

You've declared that mutexHash exists, but haven't defined it. You need to add a definition to test.cpp:
map<int, pthread_mutex_t> Test::mutexHash;

Related

How can I implement a fallback function when some function is missing(at compile time)?

My goal is:
if pthread_setname_np is defined in glibc, we will use glibc's version.
otherwise, we will use a fallback function pthread_setname_np which actually do nothing to prevent compile errors.
This need to be done at compile time.
So I write the following codes
#include <cstdio>
#include <pthread.h>
__attribute__((weak)) int pthread_setname_np(pthread_t thread, const char *name) { printf("foo\n"); return 0; }
int main() {
pthread_setname_np(pthread_self(), "bar");
}
IMO, if I run g++ test_free_bsd.cpp -o test_free_bsd -lpthread, since the symbol is already defined in pthread, so the compile will not link my self-defined symbol.
However, the program still prints out "foo", which means it actually uses my weak symbol.
Then it occurred to me that my self-defined pthread_setname_np is in the same unit with main, there are no linking. So I changed to the following
// g++ test_free_bsd.cpp test_free_bsd2.cpp -o test_free_bsd -lpthread
// test_free_bsd.cpp
#include <cstdio>
#include <pthread.h>
int main() {
pthread_setname_np(pthread_self(), "bar");
}
// test_free_bsd2.cpp
#include <cstdio>
#include <pthread.h>
__attribute__((weak)) int pthread_setname_np(pthread_t thread, const char *name) { printf("foo\n"); return 0; }
However, the program still prints out foo. So I am lost here. IMO, in test_free_bsd.cpp, it will link pthread_setname_np in glibc, rather than in test_free_bsd2.cpp which is a weak symbol.
=== UPDATE ===
Why I wan to do this? There is a fallback in codes of Clickhouse. I am using these codes in my project, though I don't know why they are here. However, I don't want to change its behavior. I only want these lines to take effects only we are sure the glibc we linked to do not has pthread_setname_np.
On FreeBSD pthread_setname_np seems to exists, it is defined in pthread_setname_np.h. I don't know why you get a linker error (I can't test it.)
However, you should be able to use #ifndef _GNU_SOURCE around your pthread_setname_np to only define it if it isn't defined by pthread.h.

Pass reference of a smart ptr to a constructor

i use qcc (qnx 660) compiler (gcc 4.7.3).
I wanted to use a reference to an object in another object.
For this I wanted to pass this in a constructor call and copy/assign it to a member instance.
As I got undefined reference errors again and again I got annoyed and converted the whole thing in a simpler way and changed a refrenz to an int variable, see example.
I came across this question, and wanted to solve it in the answer as given by #sellibitze.
Here is my code example:
foo.hpp:
#include <memory>
#include <utility>
class foo { public:
explicit foo(std::shared_ptr<int> stuff);
private:
std::shared_ptr<int> mstuff;
};
foo.cpp:
#include "foo.hpp"
explicit foo::foo(std::shared_ptr<int> stuff)
:mstuff(std::move(stuff))
{
std::cout << "done" << std::endl;
}
main.cpp:
#include <cstdlib>
#include <iostream>
#include "foo.hpp"
int main(int argc, char *argv[])
{
foo my_foo(std::make_shared<int>(10));
}
error message of compiler:
main.cpp:11: undefined reference to `foo::foo(std::shared_ptr)'
As this didn't work either, I got suspicious and recreated the example in the online compiler, https://godbolt.org/z/83hTMq1ef.
With the gcc 4.7.3 various messages come.
With a gcc >9 you only get this message :
:17:1: error: 'explicit' outside class declaration 17 |
explicit foo::foo(std::shared_ptr cnt)
| ^~~~~~~~ Compiler returned: 1
What is the smartest way to pass a shared_ptr with gcc version 4.7.3?

Undefined reference to a defined method

So I was trying to access a method that is defined in another class and has the prototype in the header. I'm pretty positive I defined it but it keeps popping up undefined reference to SafeCracker.
Main.cpp
#include <iostream>
#include "mystuff.h"
using namespace std;
void BigDog(int KibblesCount);
int main()
{
cout << SafeCracker(1);
return 0;
}
mystuff.cpp
#include <iostream>
using namespace std;
string SafeCracker(int SafeID)
{
return "123456";
}
mystuff.h
using namespace std;
#ifndef MYSTUFF_H_INCLUDED
#define MYSTUFF_H_INCLUDED
string SafeCracker(int SafeID);
#endif // MYSTUFF_H_INCLUDED
Here it tells you that you have an undefined reference, so you don't really have a problem with the prototype.
Had you forgotten to include the header file that contains the prototype you would have gotten something like
main.cpp: In function ‘int main()’:
main.cpp:8:13: error: ‘SafeCracker’ was not declared in this scope
cout << SafeCracker(1);
Your undefined reference is a linker error. The most likely cause would be that you did not use mystuff.cpp when compiling
If you're compiling from the command line, you should give both files as parameters.
If you're using an IDE that calls the compiler, make sure that the file is part of the project.
For example in Code::Blocks right-click on the file name and go "add to project" (If I remember correctly)
It is also possible that you made a typo in the function declaration in mystuff.cpp (that doesn't seem to be the case here though)
Now there is one important thing about your code you should take note of:
It is very bad practice to put a using namespace in a header file.
using namespace std; in a .cpp source file is mostly up to you, and that using statement will only apply to that particular file.
But if you put it in a header file that is meant to be included through #include , the using there will be forced upon any code that includes it.
Here is an example:
main.cpp
#include <iostream>
// including mystuff.h to use that awesome SafeCracker()
#include "mystuff.h"
// I need to use an std::map (basically an associative array)
#include <map>
// the map of my game
class map
{
int tiles[10][10];
};
int main()
{
// The std map I need to use
std::map<int, int> mymappedcontainer;
// The map of my game I need to use
map mytiles;
// The reason why I need to include mystuff.h
cout << SafeCracker(1);
return 0;
}
Normally, my class map should not be a problem since the map I included from the standard library is inside the namespace std, so to use it you would need to go std::map.
The problem here is that, since mystuff.h has using namespace std; in it, the symbol map is already used, and that creates a conflict.
You do not now who will use your header files, or if you will use them again a long time from now, and maybe then you will want to use name that is already used in the std namespace.
I advise you to use std:: before things taken from the standard libraries instead (std::string instead of just string for example)
PS: In C++, "class" refers to a class data structure, and the functions you made here are not part of any class. You should say "defined in another file" or "defined in another translation unit" instead

C++ error: 'unordered_map' does not name a type

I am doing everything correctly as far as I can tell and I have gotten the error message:
error: 'unordered_map' does not name a type
error: 'mymap' does not name a type
In my code, I have:
#include <unordered_map>
using namespace std;
//global variable
unordered_map<string,int> mymap;
mymap.reserve(7000);
void main {
return;
}
I don't see what can be missing here....
EDIT: when I update my declaration to
std::tr1::unordered_map<string,int> mymap;
I an able to eliminate the first error, but when I try to reserve, I still get the second error message.
EDIT2: As pointed out below, reserve must go into main and I need to compile with flag
-std=c++0x
However, there still appear to be errors related to unordered_map, namely:
error: 'class std::tr1::unordered_map<std::basic_string<char>, int>' has no member named 'reserve'
Compile with g++ -std=c++11 (my gcc version is gcc 4.7.2) AND
#include <unordered_map>
#include <string>
using namespace std;
//global variable
unordered_map<string,int> mymap;
int main() {
mymap.reserve(7000); // <-- try putting it here
return 0;
}
If you want to support <unordered_map> for versions older than c++11 use
#include<tr1/unordered_map> and declare your maps in the form :- std::tr1::unordered_map<type1, type2> mymap
which will use the technical report 1 extension for backward compatibility.
You can't execute arbitrary expressions at global scope, so you should put
mymap.reserve(7000);
inside main.
This is also true for other STL containers like map and vector.

Undefined reference to a static method

I m trying to compile this code and linking fails with the following error:
this is how i m compiling it;
g++ logtester.cc -I/home/foo/include -L/home/foo/lib -llog4cxx
/tmp/ccADKreY.o(.text+0x120): In function `main': undefined reference to `FrameworkLogger::getInstance()'
collect2: ld returned 1 exit status
Why? how can i fix it?
#include <log4cxx/logger.h>
#include <log4cxx/xml/domconfigurator.h>
using namespace log4cxx;
using namespace log4cxx::xml;
using namespace log4cxx::helpers;
class FrameworkLogger
{
private:
FrameworkLogger();
LoggerPtr logger;
public:
static LoggerPtr getInstance();
};
(Another file:)
#include "FrameworkLogger.h"
#include <iostream>
LoggerPtr FrameworkLogger::getInstance()
{
std::cout<<"test";
}
(Yet another file:)
#include "FrameworkLogger.h"
#include <iostream>
using namespace std;
int main(){
// LoggerPtr logger =
FrameworkLogger::getInstance();
std::cout<<"test";
}
This sounds like a linker error. Ensure that you are properly linking all of your object files
You need to list all compilation units (.cc files) in the compiler invocation:
g++ logtester.cc the-file-you-have-not-named.cc -I/home/foo/include -L/home/foo/lib -llog4cxx