I have a problem with the code that uses function pointer that takes shared_ptr argument.
Here is a sample code.
header.h
#include <functional>
#include <iostream>
template <class T> class FuncWrapper{
private:
void (*original_function)(T a);
public:
void setFunction(void *func);
void execFunction(T a, void *data);
};
template <class T> void FuncWrapper<T>::setFunction(void *func){
original_function = (void (*)(T))func;
}
template <class T> void FuncWrapper<T>::execFunction(T a, void *data){
FuncWrapper<T>* wrapper = (FuncWrapper<T>*)data;
std::cout << "inside wrapper " << *(a.get()) << std::endl;
wrapper->original_function(a);
}
main.cpp
#include <iostream>
#include <memory>
#include "header.h"
class ClassA{
public:
ClassA(std::shared_ptr<int> a){
FuncWrapper<std::shared_ptr<int>> *fw;
fw = new FuncWrapper<std::shared_ptr<int>>;
fw->setFunction((void*)&ClassA::print_int);
std::function<void(std::shared_ptr<int>)> g = std::bind(&FuncWrapper<std::shared_ptr<int>>::execFunction, fw, std::placeholders::_1, fw);
g(a);
delete fw;
}
private:
void print_int(std::shared_ptr<int> x) {
std::cout << "printing int" << std::endl;
std::cout << "given int " << *(x.get()) << std::endl;
}
};
int main(int argc, char * argv[]){
std::shared_ptr<int> x = std::make_shared<int>(10);
std::cout << "inside main " << *(x.get()) << std::endl;
ClassA *temp;
temp = new ClassA(x);
delete temp;
return 0;
}
Result
inside main 10
inside wrapper 10
printing int
Segmentation fault (core dumped)
I cannot figure out why it causes segmentation fault.
Changing std::shared_ptr<int>
to int
works just fine.
Therefore I assume that it has to do with owenership of shared_ptr, but I'm not familiar with smart pointers and I'm completely at loss.
I want to know
Limitations are
print_int
function itselfFuncWrapper<T>::execFunction
FuncWrapper<T>::execFunction
has to be staticOtherwise, it is free to change. (inside ClassA
constructor, inside main
execFunction
etc.)
The problem is not the shared_ptr, but mismatch between pointers to a function and a member function.
Your function wrapper expects a pointer to a function (void (*)(std::shared_ptr<int>)
), but you provide a pointer to a member function (void (ClassA::*)(std::shared_ptr<int>)
), which is different. An implicit leading argument of pointer to this is added to it.
This is how it really looks like:
// pointer to member function
void (*)(ClassA *ptr, std::shared_ptr<int>)
Your shared_ptr goes to the first argument and fortunately the application segfaults.
One of the solutions is to make the function print_int
static.
class ClassA{
public:
ClassA(std::shared_ptr<int> a){
FuncWrapper<std::shared_ptr<int>> *fw;
fw = new FuncWrapper<std::shared_ptr<int>>;
fw->setFunction((void*)&ClassA::print_int);
std::function<void(std::shared_ptr<int>)> g = std::bind(&FuncWrapper<std::shared_ptr<int>>::execFunction, fw, std::placeholders::_1, fw);
g(a);
delete fw;
}
private:
static void print_int(std::shared_ptr<int> x) {
std::cout << "printing int" << std::endl;
std::cout << "given int " << *(x.get()) << std::endl;
}
};
But there seems to be another problem in your code. Function pointers should not be converted to object pointers (which void * is). Maybe change your setFunction this way:
void setFunction(void (*func)(T)) {
original_function = func;
}
More on that here