C++11: Undefined symbols for arcitechture [duplicate] - c++11

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 8 years ago.
I'm having a weird problem (at least in my eyes) with C++. I've created a thread pool class, and in the main function I just pushes one element to the task queue.
This gives me an error saying "undefined symbols". When the specific line is commented out, the program compiles.
Here is the push method in question:
template<class F, class ...Args>
void concurrency::thread_pool::push(F&& f, Args&&... args) {
if (stop) {
throw std::runtime_error("push on stopped thread_pool");
}
std::function<void()> func = std::bind(f, args...);
lockGuard l(mutex);
bool should_wake = queue.empty();
queue.push(func);
if (should_wake) {
cond.notify_one();
}
}
And here's the main function:
void hello_world() {
std::cout << "Hello, World!" << std::endl;
}
int main() {
pool = new concurrency::thread_pool(5);
pool->push(hello_world); // <-- Compile error!
}
This is the command:
david$ g++ -g -Wall -std=c++0x -I ./ *.cpp
Undefined symbols for architecture x86_64:
"void concurrency::thread_pool::push<void (&)()>(void (&)())", referenced from:
_main in ccuKcG16.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
And my g++ version:
davids-mbp:cpp-thread-pool david$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/local/Cellar/gcc47/4.7.3/libexec/gcc/x86_64-apple-darwin13.0.2/4.7.3/lto-wrapper
Target: x86_64-apple-darwin13.0.2
Configured with: ../configure --build=x86_64-apple-darwin13.0.2 --prefix=/usr/local/Cellar/gcc47 /4.7.3 --enable-languages=c,c++,objc,obj-c++ --program-suffix=-4.7 --with-gmp=/usr/local/opt/gmp4 --with-mpfr=/usr/local/opt/mpfr2 --with-mpc=/usr/local/opt/libmpc08 --with-ppl=/usr/local/opt/ppl011 --with-cloog=/usr/local/opt/cloog-ppl015 --with-system-zlib --enable-version-specific-runtime-libs --enable-libstdcxx-time=yes --enable-stage1-checking --enable-checking=release --enable-lto --disable-werror --enable-plugin --disable-nls --disable-multilib
Thread model: posix
gcc version 4.7.3 (GCC)
Update
thread_pool.hpp: http://pastebin.com/62SDD0ZY
thread_pool.cpp: http://pastebin.com/nqz57HS9

Your problem might be reduced to
g++ linking order dependency when linking c code to c++ code
Because you use *.cpp in your command line
Update
I'm afraid your post doesn't provide enought information, but I bet your problem is
Storing C++ template function definitions in a .CPP file

Related

Cuda C++ template undefined reference Compilation issue while porting a visual studio project to linux

I am trying to compile the following code ([cuShiftOr]) to a linux box. Original code is running on Visual Studio 2013 in Windows.
My strategy is to compile all .cu files like below:
nvcc -std=c++11 -Icpp11-range -gencode=arch=compute_52,code=\"sm_52,compute_52\" --use-local-env --cl-version 2013 -maxrregcount=0 --machine 64 --compile -cudart static -DWIN32 -DWIN64 -DNDEBUG -D_CONSOLE -D_MBCS -I$HOME/cuShiftOr/CuShiftOr -I$HOME/cuShiftOr/CuShiftOrBenchmark -I$HOME/cuShiftOr/tinyformat -Xcompiler "-fPIC -fexceptions -ffunction-sections -fdata-sections -fpermissive" -ccbin=/opt/cray/pe/craype/2.5.10/bin/CC -c CuShiftOr/device/hybrid.cu -o objs/CuShiftOr/device/hybrid.cu.o
Likewise for the rest.
At the final stage link everything together by running:
nvcc -std=c++11 -Icpp11-range -gencode=arch=compute_52,code=\"sm_52,compute_52\" --use-local-env --cl-version 2013 -maxrregcount=0 --machine 64 -cudart static -DWIN32 -DWIN64 -DNDEBUG -D_CONSOLE -D_MBCS -I$HOME/cuShiftOr/CuShiftOr -I$HOME/cuShiftOr/CuShiftOrBenchmark -I$HOME/cuShiftOr/tinyformat -Xcompiler "-fPIC -std=c++11 -Icpp11-range -fexceptions -ffunction-sections -fdata-sections -fpermissive -Wnon-template-friend" -ccbin=/opt/cray/pe/craype/2.5.10/bin/CC -o CuShiftOrBenchmark.a objs/CuShiftOr/device/hybrid.cu.o objs/CuShiftOr/util/op.cu.o objs/CuShiftOr/device/segment.cu.o objs/CuShiftOr/host.cu.o objs/CuShiftOr/util/timer.cu.o objs/CuShiftOr/util/file.cu.o objs/CuShiftOr/util/generator.cu.o objs/CuShiftOrBenchmark/kernel.cu.o -lm
However that leads me this undefined reference issue:
objs/CuShiftOrBenchmark/kernel.cu.o: In function `void run_benchmark<unsigned int>(std::ostream&, cushiftor::device::Handler<unsigned int>*, long, unsigned int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
tmpxft_00003ea2_00000000-4_kernel.cudafe1.cpp:(.text._Z13run_benchmarkIjEvRSoPN9cushiftor6device7HandlerIT_EEljiNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_Z13run_benchmarkIjEvRSoPN9cushiftor6device7HandlerIT_EEljiNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0x203): undefined reference to `cushiftor::util::op::bit<unsigned int>::size'
collect2: error: ld returned 1 exit status
inside op.cuh it is defined as:
template<typename type>
struct bit {
static const int size = sizeof(type) * 8;
};
template<typename word>
__host__ __device__ __forceinline__ word ones(int m) {
return ~word(0) >> (bit<word>::size - m);
}
and then on kernel.cu we have:
#include "util/op.cuh"
using cushiftor::util::op::bit;
using cushiftor::util::op::bytepack;
using cushiftor::util::op::div_up;
using cushiftor::util::op::round_up;
using cushiftor::util::op::shuffle_up;
Further more compiling with Visual Studio 2013 (which works since the project was made on that) shows some instantiations that I am not sure if g++ is doing e.g:
2>C:/Users/A/Desktop/cuShiftOr/CuShiftOrBenchmark/kernel.cu(209): warning C4244: 'argument' : conversion from 'int64_t' to 'cushiftor::env::datasize_t', possible loss of data
2> C:/Users/A/Desktop/cuShiftOr/CuShiftOrBenchmark/kernel.cu(230) : see reference to function template instantiation 'void benchmark_with_file<word>(cushiftor::device::Handler<word> *)' being compiled
2> with
2> [
2> word=unsigned int
2> ]
2>C:/Users/A/Desktop/cuShiftOr/CuShiftOrBenchmark/kernel.cu(86): warning C4018: '<=' : signed/unsigned mismatch
2> C:/Users/A/Desktop/cuShiftOr/CuShiftOrBenchmark/kernel.cu(132) : see reference to function template instantiation 'void run_benchmark<word>(std::ostream &,cushiftor::device::Handler<word> *,int64_t,cushiftor::env::datasize_t,int,std::string)' being compiled
2> with
2> [
2> word=unsigned int
2> ]
Now my C++11 template knowledge is very limited but I did try to instantiate also inside the kernel.cu by adding:
template class cushiftor::util::op::bit<unsigned int>;
However to no avail... Any tips are very welcomed!
I believe this question is essentially a duplicate of this one. However simply marking it as such with no explanation may be a bit obscure. Therefore I'm going to provide a CW answer in the hopes that someone may improve it or correct me if I am wrong.
A possible MCVE derived from the code is as follows (note that I'm converting to using g++ directly rather than nvcc, as the manifestation and workarounds are the same):
$ cat test.cpp
#include <iostream>
namespace cushiftor {
namespace util {
namespace op {
template<typename type>
struct bit {
static const int size = sizeof(type) * 8;
};
}
}
}
#ifdef FIX2
void f(const int data){
#else
void f(const int &data){
#endif
std::cout << "size of type in bits is: " << data << std::endl;
}
using cushiftor::util::op::bit;
#ifdef FIX1
template <typename T> const int bit<T>::size;
#endif
template<typename word>
void run_benchmark() {
f(bit<word>::size);
}
int main(){
run_benchmark<unsigned>();
}
$ g++ -o test test.cpp
/tmp/ccCW51e3.o: In function `void run_benchmark<unsigned int>()':
test.cpp:(.text._Z13run_benchmarkIjEvv[_Z13run_benchmarkIjEvv]+0x5): undefined reference to `cushiftor::util::op::bit<unsigned int>::size'
collect2: error: ld returned 1 exit status
$ g++ -DFIX1 -o test test.cpp
$ g++ -DFIX2 -o test test.cpp
$
This MCVE was created based on inspection of relevant code in kernel.cu, tinyformat.h, and op.cuh, in the original cuShiftOr project (and paper).
We see that if we compile the code as-is, it generates a similar error to that reported in the question.
Compiling with -DFIX2 demonstrates that taking the item in question (bit::size) as a reference argument is essential to witnessing of the issue.
Compiling with -DFIX1 eliminates the issue, and I believe is the correct approach in this case.
The explanation for this issue seems to be that the compiler may treat the static const member as a compile-time constant, unless it is "used" in the code. ("Used" has a special language-specific meaning here.) If it is "used" in the code, then the compiler must be able to take the address of it (sensible in the case of a reference parameter) and to take the address of it, the class/struct definition is not sufficient. (It is apparently only a declaration even though it appears in the class/struct definition. The declaration is sufficient for usage equivalently to a compile-time constant, but is not sufficient for the case where we wish to take the address of it.)
From here:
If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19) In that case, the member can appear in integral constant expressions. The member shall still be defined in a namespace scope if it is used in the program
I believe the FIX1 code modification satisfies the bolded requirement above.
With the above preamble, I believe it is valid to mark this as a duplicate.
With respect to the behavior of the original project on windows, I would conjecture that compilers may have leeway in enforcement of this, and may in fact provide referenceable member symbols even when the program does not explicitly define them.

Cannot use nana library

I try to use Nana library with Code::Block IDE. I made all settings like here
and add -std=C++11 flag and Boost include path but it's print next error on building:
nana/include/nana/paint/graphics.hpp|143|error: ‘unsigned int nana::paint::graphics::bidi_string(const nana::point&, const char*, std::size_t)’ cannot be overloaded|
nana/include/nana/paint/graphics.hpp|142|error:
with ‘unsigned int nana::paint::graphics::bidi_string(const nana::point&, const char_t*, std::size_t)’|
I only start study C++ 11 standart and Nana GUI library and cannot understand these bugs.
I faced the same problem.
To solve problem I look at how nana it self deal with this problem by compiling nana with make VERBOSE=1,
and take defines from it.
So to compiled example:
#include<nana/gui.hpp>
int main()
{
using namespace nana;
form fm;
drawing{fm}.draw([](paint::graphics& graph){
graph.string({10, 10}, L"Hello, world!", colors::red);
});
fm.events().click(API::exit);
fm.show();
exec();
}
from nana site(http://nanapro.org/en-us/) I use such command line:
g++ -DNANA_ENABLE_PNG -DNANA_LIBPNG -DNANA_LINUX -DNANA_UNICODE \
-DNANA_X11 -DPLATFORM_SPEC_HPP="<nana/detail/linux_X11/platform_spec.hpp>" \
-DSTD_CODECVT_NOT_SUPPORTED -std=c++11 -I nana/include/ \
test.cpp build/libnana.a -lX11 -lXft -lpthread -lpng

std::future and clang with -stdlib=libstdc++

The following program fails to link with clang and -stdlib=libstdc++:
$ cat future.cpp
#include <iostream>
#include <future>
int main()
{
std::future<int> f1 = std::async([](){ return 42; });
f1.wait();
std::cout << "Magic number is: " << f1.get() << std::endl;
}
$ g++-mp-5 future.cpp -std=c++11 && ./a.out
Magic number is: 42
$ clang++-mp=3.5 future.cpp -std=c++11 && ./a.out
Magic number is: 42
When building with clang and -stdlib=libstdc++, the following linking error occurs:
$ clang++-mp-3.5 future.cpp -std=c++11 -stdlib=libstdc++ -I/opt/local/include/gcc5/c++ -I/opt/local/include/gcc5/c++/x86_64-apple-darwin14 -L/opt/local/lib/gcc5 -lstdc++ && ./a.out
Undefined symbols for architecture x86_64:
"std::__once_call", referenced from:
void std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) in future-b6480b.o
void std::call_once<void (std::thread::*)(), std::reference_wrapper<std::thread> >(std::once_flag&, void (std::thread::*&&)(), std::reference_wrapper<std::thread>&&) in future-b6480b.o
"std::__once_callable", referenced from:
void std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) in future-b6480b.o
void std::__once_call_impl<std::_Bind_simple<std::_Mem_fn<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*)> (std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*)> >() in future-b6480b.o
void std::call_once<void (std::thread::*)(), std::reference_wrapper<std::thread> >(std::once_flag&, void (std::thread::*&&)(), std::reference_wrapper<std::thread>&&) in future-b6480b.o
void std::__once_call_impl<std::_Bind_simple<std::_Mem_fn<void (std::thread::*)()> (std::reference_wrapper<std::thread>)> >() in future-b6480b.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
However, a simple program w/o future builds just fine, e.g.:
$ cat simple.cpp
#include <iostream>
#include <future>
int main()
{
std::cout << "Magic number is: " << 42 << std::endl;
}
$ clang++-mp-3.5 simple.cpp -std=c++11 -stdlib=libstdc++ -I/opt/local/include/gcc5/c++ -I/opt/local/include/gcc5/c++/x86_64-apple-darwin14 -L/opt/local/lib/gcc5 -lstdc++ && ./a.out
Magic number is: 42
System is OSX 10.10.4 with macports.
I can't figure out what is the problem. Thanks!
This is an incompatibility between GCC and Clang on Mac OS X.
GCC emits a reference to ___emutls_v._ZSt15__once_callable while clang emits a reference to __ZSt15__once_callable.
Unfortunately, __ZSt15__once_callable and ___emutls_v._ZSt15__once_callable
are not compatible, so doing something like:
asm("__ZSt15__once_callable: jmp ___emutls_v._ZSt15__once_callable");
wouldn't work either.
I also came accross this LLVM bug report: http://lists.cs.uiuc.edu/pipermail/llvmbugs/2014-August/035744.html which probably means clang will never add for support GCC's emutls implementation.
Edit: It looks like support for emutls was added to clang trunk a couple of hours ago in r243438 via -femulated-tls.
Clang on OSX uses an older version of libstdc++. I believe its version 4.2 which does not support many of the C++11 features. If you want to use C++11 with clang on OSX your only choice is libc++.
You could also use gcc-4.x from homebrew which will include a newer version of libstdc++. Unfortunately clang will not easily link with this version of the standard library.
Undefined symbol std::__once_call when building GCC's standard library is explained here https://github.com/msys2/MINGW-packages/issues/5786 and should be fixed when using compiler flag -femulated-tls.

error: ‘defaultfloat’ is not a member of ‘std’

std::defaultfloat doesn't seem to be defined in GCC, despite being in the standard (I think it's §27.5.6.4). I've isolated it to this simple program:
// test.cpp
#include <iostream>
int main()
{
std::cout << std::defaultfloat << 1.3;
return 0;
}
This compiles in VC++11. I tried compiling this with g++ 4.7.2 and g++ 4.9.0 using both of these commands:
g++ test.cpp
g++ test.cpp -std=c++11
I also tried an online compile on GCC 4.8.1 here, always with the same result:
user#office-debian:~/Documents/test$ g++ test.cpp -std=c++11
test.cpp: In function ‘int main()’:
test.cpp:5:15: error: ‘defaultfloat’ is not a member of ‘std’
std::cout << std::defaultfloat << 1.3;
Why am I getting this error?
GCC libstdc++ just doesn't support these C++11 manipulators in any of
the versions you've compiled against. A patch was submitted exactly one month ago

matlab mex clang C++11 thread -> Undefined symbols error

Goal: I want to use thread STL of C++11 in Matlab mex file (R2013a) using Xcode 4.6
I modified ~/.matlab/R2013a/mexopts.sh
CC='clang++' # was llvm-gcc-4.2
CXX='clang++' # was llvm-g++-4.2
MACOSX_DEPLOYMENT_TARGET='10.8' # was 10.5. C++11 is supported >=10.7
CXXFLAGS="$CXXFLAGS -std=gnu++11 -stdlib=libc++" # additional flags
Normal mex files without C++11 features are compiled well. Further, STL is well detected by the compiler except linking failure.
>> mex mextest.cpp
Undefined symbols for architecture x86_64:
"std::__1::__thread_struct::__thread_struct()", referenced from:
void* std::__1::__thread_proxy<std::__1::tuple<void (*)()> >(void*) in mextest.o
"std::__1::__thread_struct::~__thread_struct()", referenced from:
void* std::__1::__thread_proxy<std::__1::tuple<void (*)()> >(void*) in mextest.o
"std::__1::__thread_local_data()", referenced from:
void* std::__1::__thread_proxy<std::__1::tuple<void (*)()> >(void*) in mextest.o
"std::__1::__throw_system_error(int, char const*)", referenced from:
_mexFunction in mextest.o
"std::__1::thread::join()", referenced from:
_mexFunction in mextest.o
"std::__1::thread::~thread()", referenced from:
_mexFunction in mextest.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
mex: link of ' "mextest.mexmaci64"' failed.
Error using mex (line 206)
Unable to complete successfully.
The actual source code is shown below. The details are not important because it compiles well in Matlab R2013 WINDOWS version with Visual Studio 2012 Express. An equivalent cpp was also well compiled with "clang++ -std=gnu++11 -stdlib=libc++ clangtest.cpp". So, at least, there is no logical error in the codes (I'm not saying it is safe codes. It is just a test.)
#include "mex.h"
#include <thread>
#include <stdio.h>
int count_thread1 = 0;
int count_thread2 = 0;
void hello()
{
count_thread2 = 0;
for(int i=0; i<=10000; i++){
for (int j=1;j<=20000;j++){
count_thread2 = i-j-1;
}
count_thread2++;
printf("2: %d , %d\n", count_thread1, count_thread2); // Not sure if printf is thread-safe in Matlab. But it works in this particular example
}
}
void mexFunction(int nlhs,mxArray *plhs[],int nrhs,const mxArray *prhs[])
{
count_thread1 = 0;
std::thread t(hello);
for (int i=1;i<=10000;i++)
{
for (int j=1;j<=20000;j++){
count_thread1 = -i+j-1;
}
count_thread1++;
mexPrintf("1: %d , %d\n", count_thread1, count_thread2);
}
mexPrintf("\n");
t.join();
mexPrintf("Done\n");
}
It seems like I have to replace some include directories and/or library directories. What kind of options should be modify?
Thank you.
The error is due to compiling against -stdlib=libc++ but linking against -lstdc++. You can fix it in one of two ways:
Fix it in mexopts.sh. The most drastic and effective solution. Located in ~/.matlab/${MATLAB_VERSION}/mexopts.sh, this determines all compiler options. Simply find/replace all stdc++ to c++.
Patchwork solution: Simply add -lc++ to the tail end of CXXLIBS. I'm not sure what the effect of linking against multiple versions of the standard libraries is, but it seems to work. In your mex invocation, add the argument CXXLIBS="\$CXXLIBS -lc++".
As a secondary issue, I believe you're completely overwriting the value of CXXFLAGS; you must escape the $ symbol as I did above with the libraries.

Resources