I have this code:
#include <future>
#include <thread>
int main()
{
std::promise<void> p;
p.set_value();
p.get_future().get();
return 0;
}
And after compiling it with gcc it throws std::system_error:
$ g++ -o foo foo.cpp -std=c++11 -lpthread
$ ./foo
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error -1
What is weird, adding zero-second sleep before creating the promise, prevents the exception:
int main()
{
std::this_thread::sleep_for(std::chrono::milliseconds(0));
std::promise<void> p;
p.set_value();
p.get_future().get();
return 0;
}
$ g++ -o foo foo.cpp -std=c++11 -lpthread
$ ./foo
$
I tried gcc 4.8.5 and 5.4.0, same results. Why does it behave like that?
This error comes from your compilation. It should be:
g++ -o foo foo.cpp -std=c++11 -pthread
The <thread> library needs this special flag -pthread but you provided -lpthread. The former compile your translation unit with the full thread support. The later only links the library, without defining the needed macros and needed tools.
On coliru:
with -pthread: http://coliru.stacked-crooked.com/a/a53bed6696bb8d83
without: http://coliru.stacked-crooked.com/a/fd972e1556f8c060
Related
Suppose I have a function in a shared library throwing some object, and a main executable calling that function and attempting to catch that object, e.g.
decl.h
#ifndef DECL_H
#define DECL_H
void pitch();
struct MyException {
MyException();
MyException(const MyException&);
~MyException();
};
#endif
pitch.cpp
#include "decl.h"
MyException::MyException() {}
MyException::MyException(const MyException&) {}
MyException::~MyException() {}
void pitch() {
throw MyException();
}
main.cpp
#include <stdio.h>
#include "decl.h"
int main() {
try { pitch(); }
catch (MyException& e) { printf("MyException()\n"); }
catch (...) { printf("[unknown exception]\n"); }
}
Makefile
all:
$(CXX) -shared -fPIC $(CXXFLAGS) $(LTO) pitch.cpp -o libpitch.so
$(CXX) -g $(CXXFLAGS) $(LTO) main.cpp -L. -lpitch
./a.out
If I compile without link-time optimization, all is well:
CXXFLAGS="-g -O2" LTO="" make
c++ -shared -fPIC -g -O2 pitch.cpp -o libpitch.so
c++ -g -g -O2 main.cpp -L. -lpitch
./a.out
MyException()
But once I turn on link-time optimization, the thrown object is no longer caught:
CXXFLAGS="-g -O2" LTO="-flto" make
c++ -shared -fPIC -g -O2 -flto pitch.cpp -o libpitch.so
c++ -g -g -O2 -flto main.cpp -L. -lpitch
./a.out
[unknown exception]
Is this expected behavior? Is this a problem in my C++ code, or something else? This is on macOS 10.14.5:
$ c++ -v
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
This is not expected behavior.
I tested it on linux (ubuntu) with gcc 4.x, 5.x, 6.x, 7.x and 8.x and with clang 6.0. All work just fine with -O2 -flto.
Unfortunately, since I cannot reproduce it (I don't have a Mac) I can't tell you what is wrong, but it isn't your code imho.
EDIT:
I can't in good conscious say there is "nothing wrong" with your code (although I tested it as shown by you - HOWEVER, I needed to set LD_LIBRARY_PATH="." for ./a.out to work (so perhaps you are loading some other library?)) without showing you how I'd write the above code:
//decl.h:
#pragma once
#include <exception>
void pitch();
struct MyException : public std::exception
{
};
//pitch.cpp:
#include "decl.h"
void pitch()
{
throw MyException();
}
// main.cpp:
#include "decl.h"
#include <iostream>
int main()
{
try
{
pitch();
}
catch (MyException const& e)
{
std::cout << "MyException(): " << e.what() << std::endl;
}
catch (...)
{
std::cerr << "[unknown exception]" << std::endl;
}
}
Consider the following setup consisting of two shared libraries which both use a static library:
static.cpp
#include "static.h"
static int a = 0;
int getA()
{
return a++;
}
static.h
#pragma once
int getA();
shareda.cpp
#include <iostream>
#include "shareda.h"
#include "static.h"
void printA()
{
std::cout << getA() << std::endl;
}
shareda.h
#pragma once
void printA();
sharedb.cpp
#include <iostream>
#include "sharedb.h"
#include "static.h"
void printB()
{
std::cout << getA() << std::endl;
}
sharedb.h
#pragma once
void printB();
main.cpp
#include "shareda.h"
#include "sharedb.h"
int main()
{
printA();
printA();
printB();
printA();
printB();
return 0;
}
I compiled and ran these files with the following commands (using Clang 3.8.0, compiled from source, and 64-bit Debian with GNU ld 2.25):
clang++ -c static.cpp -o static.o -fPIC
ar rcs libstatic.a static.o
clang++ -c shareda.cpp -o shareda.o -fPIC
clang++ -shared -o libshareda.so shareda.o libstatic.a
clang++ -c sharedb.cpp -o sharedb.o -fPIC
clang++ -shared -o libsharedb.so sharedb.o libstatic.a
clang++ -L. -lshareda -lsharedb -o main main.cpp
LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./main
To my surprise, the output was the following:
0
1
2
3
4
My expectation was this:
0
1
0
2
1
Apparently, despite the static keyword in front of a in static.cpp, only one instance of a exists. Is there a way to have two instances of a, one for each of the shared libraries?
Apparently, despite the static keyword in front of a in static.cpp, only one instance of a exists.
That is incorrect: two instances of a exist, but only one is actually used.
And that is happening because (contrary to your expectations) printB calls the first getA available to it (the one from libshareda.so, not the one from libsharedb.so). That is one major difference between UNIX shared libraries and Windows DLLs. UNIX shared libraries emulate what would have happened if your link was:
clang++ -L. -o main main.cpp shareda.o sharedb.o libstatic.a
So what can you do to "fix" this?
You could link libsharedb.so to prefer its own getA, by using -Bsymbolic.
You could hide getA inside libsharedb.so completely (as if it's a private implementation detail):
clang++ -c -fvisibility=hidden -fPIC static.cpp
ar rcs libstatic.a static.o
clang++ -shared -o libsharedb.so sharedb.o libstatic.a
You could achieve similar result using linker version script.
P.S. Your link command:
clang++ -L. -lshareda -lsharedb -o main main.cpp
is completely backwards. It should be:
clang++ -L. -o main main.cpp -lshareda -lsharedb
The order of sources/object files and libraries on command line matters, and libraries should follow object files that reference them.
I made a program to test my knowledge on class but I had some troubles.
foo.h:
#include <iostream>
using namespace std;
class foo
{
private:
int a;
public:
foo();
};
foo.cc:
#include <iostream>
#include "foo.h"
using namespace std;
foo::foo()
{
a = 0;
}
And main.cc:
#include<iostream>
#include "foo.h"
int main()
{
foo a;
return 0;
}
I compiled this with g++ main.cc -o main. Then I got
-bash-4.1$ g++ main.cc -o main
/tmp/cc5Hnes8.o: In function `main':
main.cc:(.text+0x10): undefined reference to `foo::foo()'
collect2: ld returned 1 exit status
I think there should be a really stupid mistake here but I really cannot find it. I've been struggling on this whole night...
Appreciate any help!
You are asking the compiler to not only translate main.cc but also perform the final link to produce the executable main. This second step cannot be done because main.cc references the function foo::foo whose definition is in foo.cc and therefore not available to the compiler. You can do this:
g++ main.cc -c -o main.o
g++ foo.cc -c -o foo.o
g++ main.o foo.o -o main
The -c flag makes the compiler perform translation only, so this separately compiles main.cc and foo.cc and then links the objects together to obtain the executable. In this way, the definition of foo::foo will end up inside foo.o and will be available at link time.
Or, you can just provide both .cc files. This basically does the same thing as the three commands above:
g++ main.cc foo.cc -o main
You should compile all source (.cc in your case) files:
g++ main.cc foo.cc -o main
When you realize the constructor of foo in foo.cc, you should compile it.
use g++ main.cc foo.cc -o main.
i'm having something like these files:
libfoo.h
class foo
{
public:
foo() = default;
virtual ~foo();
};
libfoo.cpp
#include "libfoo.h"
foo::~foo() { /* code here */ }
test.cpp
#include <libfoo.h>
int main()
{
foo f;
}
i compile libfoo.h and libfoo.cpp into a shared library and all that is fine.
but when i then try to use the library in test.cpp i get undefined reference to the destructor ~foo().
this error however does not occur if i define the destructor directly in libfoo.h. i have this problem with all functions defined outside the class in my library so im guessing it has something to do with the compilation process (it compiles fine however)
i compile the library like this:
g++ -std=c++0x -Wall -Werror -fPIC -c -o libfoo.o libfoo.cpp
g++ -shared libfoo.o -o libfoo.so
any ideas as to what i might be doing wrong?
(all the functions that i declare inclass, like template functions works fine and causes no undefined reference)
I tried to reproduce the error, but I failed.
I created the files (with slight modifications):
// libfoo.h
struct foo { virtual ~foo(); };
// libfoo.cpp
#include "libfoo.h"
foo::~foo() {}
// test.cpp
#include "libfoo.h"
int main() { foo f; }
Built like this:
$ g++ -std=c++0x -Wall -Werror -fPIC -c -o libfoo.o libfoo.cpp
$ g++ -shared libfoo.o -o libfoo.so
$ g++ test.cpp -L. -lfoo
And ran like this:
$ env LD_LIBRARY_PATH=. ./a.out
I got no errors. Are you sure there is a problem with your code?
Since the definition of template must be put in header file, so I don't like it if the template class is big. so I want to make a normal class with some templated methods. Putting the defintion of templated method into header file, for others, put them into c++ source files. So here is what I am thinking.
// lambda.h
#include <iostream>
class X {
public:
std::function<bool(int)> filter;
template <class F>
void setFilter(F fn) {
filter = fn;
}
void big_function(int x);
};
// cat lambda.cpp
#include <iostream>
#include "lambda.h"
void X::big_function(int x) {
if (filter(x)) std::cout << x << std::endl;
}
// main2.cpp
#include <stdlib.h>
#include "lambda.h"
class Filter {
public:
bool operator()(int x) { return true; }
};
int main() {
X x;
x.setFilter(Filter());
x.big_function(3);
return 0;
}
// cat 2.sh
g++ -c lambda.cpp -ggdb
g++ -c main2.cpp -ggdb -std=c++11
g++ -o main2 main2.o lambda.o -ggdb
this program can compile, but got segment fault during executing (x.big_function(3));
#update
Q1: is my thinking is reasonable? is there any obvious error in my code?
Answer: Yes, it is reasonable, and no obvious error. Thanks to the first 4 comments, I did more test and works.
Q2: actually if I compile with -std=c++11, I will got segment fault. but no segment fault if I don't use std=c++11. ( I tried c++11 yesterday because I used lambda expression rather than function object for "Filter" at beginning). And it my real case, I can't discard c++11 features.
Answer: shame about my fault. fixed the issue by adding -std=c++11 for every compile unit.
zhifan$ sh -x 2.sh
+ g++ -c lambda.cpp -ggdb
+ g++ -c main2.cpp -ggdb
+ g++ -o main2 main2.o lambda.o -ggdb
zhifan$ ./main2
3
zhifan$ vim 2.sh
hifan$ sh -x 2.sh
+ g++ -c lambda.cpp -ggdb **-std=c++11**
+ g++ -c main2.cpp -ggdb -std=c++11
+ g++ -o main2 main2.o lambda.o -ggdb
zhifan$ ./main2
Segmentation fault: 11
zhifan$ g++ -v
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.4.0
Thread model: posix