Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

function callback using std::bind causes segmentation fault

Tags:

c++

boost

I have a class (let's call this "Common") that is used to create timers and call a member function from another class (let's call this "A") when the timer expires. The general idea is this: - A calls a function from Common passing it a pointer to the member function that is to be executed when the timer expires - Common stores the pointer to the function in a map with key of timer id - When the timer hits, the map is searched for the matching key and then the associated function is called.

Here is the code for A:

void A::setTimer()
{ 
   std::function<void(void)> handler = std::bind(&A::onEventFunc, this);
   pCommon->scheduleTimer(&handler);
}

onEventFunc is a public function of class A that does something when the timer expires.

Here is the code for Common:

static void timerHandler(int sig, siginfo_t *si, void uc)
{
   map<timer_t*, std::function<void>(void)>*)::iterator iter = 
                                globalTimerMap.find((timer_t*)si->si_value.sival_ptr);
   if (iter != globalTimerMap.end)
   {
      std::function<void>(void)>* handler = iter->second;
      (*handler)();
   }
}

Common::schedulerTimer(std::function<void>(void)* handler)
{
   // uses Linux timer_create and timer_settime
   // code for these excluded EXCEPT the relevant lines
   sa.sa_sigaction = timerHandler;

   // bunch of other code here for timer_create and timer_settime

   // insert into map
   globalTimerMap.insert(pair(&timerid, handler);
}

This all compiles and runs just fine UNTIL it hits the (*handler)(); line which gives a segmantation fault.

I am new to boost and Linux programming and any knowledge that I have with C++ was gained from on the job training. This makes me believe that I am doing something really silly/stupid but I just don't know what it is. Is what I am trying to do even supposed to work?

like image 418
user3348501 Avatar asked Mar 20 '23 11:03

user3348501


1 Answers

The following line:

std::function<void(void)> handler = std::bind(&A::onEventFunc, this);

This creates a local variable on the stack (local to your setTimer member function). What this means is your pointers in your map are all pointing to invalid memory.

I would change your map to store actual std::function objects rather than pointers. If you insist on storing pointers in your map, you will need to dynamically allocate the memory so that the memory remains valid:

std::function<void(void)>* handler = new std::function<void()>(std::bind(&A::onEventFunc, this));

However, you would be then required to delete the memory to avoid memory leaks, so another alternative would be to use std::unique_ptr in your map to handle that.

like image 67
Jesse Good Avatar answered Mar 23 '23 00:03

Jesse Good