Error of threads in C++ "static assertion failed" - c++

I made a quick summary of a project i have,
in which I have two threads that should be able to read and write on a common variable (protected by a mutex in the real project.
I don't understand this error
the two threads are in theory launched by a main thread
this main thread is a function of the object whose role is to manage the sub threads of this object.
I d'ont know if this is possible
main.cpp
#include <thread>
#include "Object.h"
using namespace std;
int main(){
Object tmp;
tmp.ChangeSetting(42);
thread mainthread(&Object::MainTread, &tmp);
mainthread.join();
}
Object.h
#ifndef SRC_OBJECT_H_
#define SRC_OBJECT_H_
#include <thread>
#include <iostream>
using namespace std;
class Object {
private:
int stupidvalue;
void subThread1();
void subThread2();
public:
void MainTread();
void ChangeSetting(int psvalue);
Object();
virtual ~Object();
};
#endif /* SRC_OBJECT_H_ */
Object.cpp
#include "Object.h"
void Object::subThread1(){
cout << "subthread1";
}
void Object::subThread2(){
cout << "subthread2";
}
void Object::MainTread(){
thread tmp1(subThread1);
thread tmp2(subThread2);
tmp1.join();
tmp2.join();
}
Object::Object() {
stupidvalue = 0;
}
void Object::ChangeSetting(int psvalue){
stupidvalue = psvalue;
}
Object::~Object() {
}
and my error
Info: Internal Builder is used for build
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\main.o" "..\\src\\main.cpp"
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\Object.o" "..\\src\\Object.cpp"
In file included from ..\src\Object.h:5,
from ..\src\Object.cpp:2:
C:/msys64/mingw32/include/c++/10.2.0/thread: In instantiation of 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (Object::*)(); _Args = {}; <template-parameter-1-3> = void]':
..\src\Object.cpp:13:24: required from here
C:/msys64/mingw32/include/c++/10.2.0/thread:136:44: error: static assertion failed: std::thread arguments must be invocable after conversion to rvalues
136 | typename decay<_Args>::type...>::value,
| ^~~~~
10:26:25 Build Failed. 1 errors, 0 warnings. (took 1s.304ms)
I read that it could be a typing error, but there is no parameter.

subThread1 and subThread2 are also member functions. You need to use pointer-to-member-function syntax like you did in main()
void Object::MainTread(){
thread tmp1(&Object::subThread1, this);
thread tmp2(&Object::subThread2, this);
tmp1.join();
tmp2.join();
}
Or use lambdas like the other answer suggests.

You are passing non-static method without object itself:
thread tmp1(subThread1); //error: subThread() cannot be invoked without object
You could make a lambda:
// passing this to lambda ok solong the object itself outlives the lambda ...
// in your case ok because joining in place.
thread tmp1([this]() { this->subThread(); });
Otherwise if thread could outlive the object, you would normally make a shared pointer (this way the object would leave through the shared_pointer at least as long as thread itself):
thread tmp1([self=this->shared_from_this()]() { self->subThread(); });
For this to work, Object would need to inherit from std::enable_shared_from_this<Object>:
class Object : public std::enable_shared_from_this<Object> {...}

Related

Potential memory leak if a tuple of a unique pointer is captured in lambda

clang-tidy and scan-build warn about a potential memory leak in this code:
#include <tuple>
#include <memory>
int main()
{
auto lambda = [tuple = std::make_tuple(std::make_unique<int>(42))] {};
}
$ clang-tidy main.cpp -checks="clang*"
1 warning generated.
/foo/main.cpp:7:1: warning: Potential leak of memory pointed to by field '_M_head_impl' [clang-analyzer-cplusplus.NewDeleteLeaks]
}
^
/foo/main.cpp:6:44: note: Calling 'make_unique<int, int>'
auto lambda = [tuple = std::make_tuple(std::make_unique<int>(42))] {};
^~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-redhat-linux/11/../../../../include/c++/11/bits/unique_ptr.h:962:30: note: Memory is allocated
{ return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/foo/main.cpp:6:44: note: Returned allocated memory
auto lambda = [tuple = std::make_tuple(std::make_unique<int>(42))] {};
^~~~~~~~~~~~~~~~~~~~~~~~~
/foo/main.cpp:7:1: note: Potential leak of memory pointed to by field '_M_head_impl'
}
^
Is there anything I do not see, or is it a false positive?
Environment: clang 13.0.0, gcc 11.3.1.
Compile commands:
[
{
"directory": "/foo",
"command": "/usr/bin/g++ -std=c++17 /foo/main.cpp",
"file": "/foo/main.cpp"
}
]
Notes: the issue is reproducible with -std=c++17 and -std=c++20, but not with -std=c++14.
The lambda gets destructed after running out of scope, together with it is capture – and as the tuple is captured by value it gets destructed as well, together with it the smart pointer and thus the object stored there.
Try this to see:
#include <iostream>
#include <memory>
#include <tuple>
struct S
{
S() { std::cout << "constructed" << std::endl; }
~S() { std::cout << "destructed" << std::endl; }
};
int main()
{
auto lambda = [tuple = std::make_tuple(std::make_unique<S>())] {};
return 0;
}
See on godbolt.
So apparently a false positive...
An unsolved bug in clang-tidy:
https://github.com/llvm/llvm-project/issues/55219
It doesn't have anything to do with tuples or smart pointers as seen in the simplified reproduction in this comment.

Libtins: cannot use class method as packet handler within the sniff_loop even with c++11

I'm working on an small UDP traffic sniffing example using libtins. Everything worked until I started encapsulating everythin into a class. Acording the tutorial (loop sniffing section), the snifer_loop takes a template functor as an argument, and:
The call to Sniffer::sniff_loop will make the sniffer start processing packets. The functor will be called using each processed packet as its argument. If at some point, you want to stop sniffing, then your functor should return false. Otherwise return true and the Sniffer object will keep looping.
The functor object will be copy constructed, so it must implement copy semantics. There is a helper template function which takes a pointer to an object of a template parameter type, and a member function, and returns a HandlerProxy. That object implements the required operator, in which it forwards the call to the member function pointer provided, using the object pointer given:
Everything works if I use PDU data type, or if I use Packet type with an external function, but once I use Packet type with a method, I get a compiler error:
c++ -Ihandler#sha -I. -I.. -I/usr/local/include/tins -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -std=c++11 -g -fPIC -MD -MQ 'handler#sh
a/handler.cpp.o' -MF 'handler#sha/handler.cpp.o.d' -o 'handler#sha/handler.cpp.o' -c ../handler.cpp
../handler.cpp: In constructor 'Reader::Reader()':
../handler.cpp:24:77: error: cannot convert 'bool (Reader::*)(Tins::Packet&)' to 'Tins::HandlerProxy<Reader>::fun_type {aka bool (Reader::*)(Tins::PDU&)}' for argument '2' to 'Tins::Handl
erProxy<T> Tins::make_sniffer_handler(T*, typename Tins::HandlerProxy<T>::fun_type) [with T = Reader; typename Tins::HandlerProxy<T>::fun_type = bool (Reader::*)(Tins::PDU&)]'
sniffer.sniff_loop(make_sniffer_handler(this, &Reader::handlerPacket));
The tutorial specifies:
Packets can also be accepted on the functor object used on Sniffer::sniff_loop, but only when you are compiling in C++11 mode.
And I am using the c++11 switch.
#include <tins/tins.h>
using namespace Tins;
bool callbackPDU(PDU &pdu) {
return true;
}
bool callbackPacket(Packet &packet) {
return true;
}
class Reader
{
Reader()
{
Sniffer sniffer("wlp3s0");
// sniffer.sniff_loop(callbackPDU); // This works
// sniffer.sniff_loop(callbackPacket); // This also works
// sniffer.sniff_loop(make_sniffer_handler(this, &Reader::handlerPDU)); // This also works
sniffer.sniff_loop(make_sniffer_handler(this, &Reader::handlerPacket)); // This doesn't work
}
bool handlerPDU(PDU &pdu)
{
return true;
}
bool handlerPacket(Packet &packet)
{
return true;
}
};
int main()
{
Reader reader();
}
class Functor
{
Functor(){}
bool operator()(Packet &packet)
{
return true;
}
};
Ok, so according the library main developer, I should have used this:
sniffer.sniff_loop(std::bind(&Reader::handlerPacket, this, std::placeholders::_1));
And that worked like a charm.

boost::thread in-class member function call returns unique_lock instantiation error

I am using boost::thread to call an in-class member function from within a different member function of the same class. The declaration of the method I would like to thread is:
void ClassName::nnMetropolisStep(double random, std::vector<int> nums);
And I am creating threads from another member function via:
boost::thread* tThread = new boost::thread(&ClassName::nnMetropolisStep,
this,
someRandom,someNums);
These are the only calls to boost functions in the code I'm using.
I've seen in other questions that this syntax will work for non-static member functions (and there are no access issues with the way I have constructed the threads). However, when I compile, I get the following error:
g++ -fPIC -std=c++11 -c -g -Wall `root-config --cflags --glibs` -MMD -c -o obj/IsingModel.o src/IsingModel.cpp
In file included from /usr/include/boost/thread/pthread/mutex.hpp:11:0,
from /usr/include/boost/thread/mutex.hpp:16,
from /usr/include/boost/thread/pthread/thread_data.hpp:12,
from /usr/include/boost/thread/thread.hpp:17,
from /usr/include/boost/thread.hpp:13,
from src/interface/IsingModel.h:11,
from src/IsingModel.cpp:11:
/usr/include/boost/thread/locks.hpp: In instantiation of 'boost::unique_lock<Mutex>& boost::unique_lock<Mutex>::operator=(boost::unique_lock<Mutex>&&) [with Mutex = boost::mutex]':
/usr/include/boost/thread/future.hpp:414:33: required from here
/usr/include/boost/thread/locks.hpp:269:22: error: cannot bind 'boost::unique_lock<boost::mutex>' lvalue to 'boost::unique_lock<boost::mutex>&&'
swap(temp);
^
/usr/include/boost/thread/locks.hpp:279:14: note: initializing argument 1 of 'void boost::unique_lock<Mutex>::swap(boost::unique_lock<Mutex>&&) [with Mutex = boost::mutex]'
void swap(unique_lock&& other)
^
make: *** [obj/IsingModel.o] Error 1
What is going on? Clearly I am either doing something incorrectly, or worse, there's an issue with my compiler setup.
I figured out the answer by removing all references to boost except for the #include statement. In my header file, I was using
#include "boost/thread.hpp"
Which worked, but was not correct. Once I changed it to
#include "boost/thread/thread.hpp"
Everything compiled without complaint.
I'm using version 1.41.0 of boost.
You need to use boost::bind function during thread object creation. For example:
double rand = 0;
std::vector<int> myVector;
ClassName obj;
auto threadObj = new boost::thread(boost::bind(&ClassName::nnMetropolisStep,&obj,rand,myVector));

Getting error: ‘this’ is unavailable for static member functions even when function is not static

I have function, where I create new pthread and then work with it later
void Client::initialize(Client * c) {
//some unimportant code here
pthread_t thread;
pthread_create(&thread, NULL,
c->sendMessage, (void *) fd);
//some unimportant code here
}
Client::Client() {
initialize(this);
}
sendMessage function:
void * Client::sendMessage(void *threadid) {
//unimportant code here
this->showHelp();
//unimportant code here
return NULL;
}
declaration of showHelp
void Client::showHelp() {
//some code
}
When I try to compile it, I get this error:
g++ -Wall -pedantic -Wno-long-long -O0 -ggdb -pthread -lncurses -g -c ./Client.cpp
./Client.cpp: In static member function ‘static void* Client::sendMessage(void*)’:
./Client.cpp:244:13: error: ‘this’ is unavailable for static member functions
make: *** [Client.o] Error 1
How is that possible, when sendMessage is not declared as static ? Is there any way around?
Most likely your sendMessage is declared as static in class definition. Specific member function definitions are indistinguishable for static and non-static functions. You have to look at class definition to tell them apart.

Executing a member function of a class

I am trying to experiment the C++11 threads in a way that it accepts a member function of a class as a parameter into the thread constructor as shown in the first code snippet below on line 20 that is marked . The class definition is given in the 2nd code snippet. When this code is compiled, I am getting a bunch of errors shown in the 3rd snippet. Can anyone tell me what I am doing wrong? Thanks.
SNIPPET 1: Thread initialization (main_app.cpp)
#include <thread>
#include "ServiceRegistrar.hpp"
#define SERVER_TYPE 100065
#define SERVER_INST_LOWER 1
#define SERVER_INST_UPPER 2
#define TIMEOUT 500000
int main()
{
ServiceRegistrar sr1(SERVER_TYPE, TIMEOUT, SERVER_INST_LOWER, SERVER_INST_LOWER);
/*LINE 20 is the following*/
std::thread t(&ServiceRegistrar::subscribe2TopologyServer, sr1);
t.join();
sr1.publishForSRs();
}
SNIPPET 2: Class definition
class ServiceRegistrar
{
public:
ServiceRegistrar(int serverType, int serverTimeOut, int serverInstanceLower, int serverInstanceUpper)
: mServerType(serverType),
mServerTimeOut(serverTimeOut),
mServerInstanceLower(serverInstanceLower),
mServerInstanceUpper(serverInstanceUpper)
{ }
void subscribe2TopologyServer();
void publishForSRs();
void publishForServices();
private:
int mServerType;
int mServerTimeOut;
int mServerInstanceLower;
int mServerInstanceUpper;
};
SNIPPET 3: Compilation output
$ g++ -g -c -Wall -std=c++11 main_app.cpp -pthread
In file included from /usr/include/c++/4.7/ratio:38:0,
from /usr/include/c++/4.7/chrono:38,
from /usr/include/c++/4.7/thread:38,
from main_app.cpp:8:
/usr/include/c++/4.7/type_traits: In instantiation of ‘struct std::_Result_of_impl<false, false, std::_Mem_fn<void (ServiceRegistrar::*)()>, ServiceRegistrar>’:
/usr/include/c++/4.7/type_traits:1857:12: required from ‘class std::result_of<std::_Mem_fn<void (ServiceRegistrar::*)()>(ServiceRegistrar)>’
/usr/include/c++/4.7/functional:1563:61: required from ‘struct std::_Bind_simple<std::_Mem_fn<void (ServiceRegistrar::*)()>(ServiceRegistrar)>’
/usr/include/c++/4.7/thread:133:9: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (ServiceRegistrar::*)(); _Args = {ServiceRegistrar&}]’
main_app.cpp:20:64: required from here
/usr/include/c++/4.7/type_traits:1834:9: error: no match for call to ‘ (std::_Mem_fn<void (ServiceRegistrar::*)()>) (ServiceRegistrar)’
Apparently it's a gcc 4.7 bug...use
std::thread t(&ServiceRegistrar::subscribe2TopologyServer, &sr1);
instead.
EDIT: actually, you probably don't want to be copying sr1 to the thread-local-storage of t, so this is better anyway.
Try:
std::thread t(std::bind(&ServiceRegistrar::subscribe2TopologyServer, sr1));
Hope it helps.