daohu527
daohu527

Reputation: 512

std::bind is on stack?

I want to pass c++ objcet member callback func to an "c" lib, which just have void*. Then I use std::function to register the callback handler. But there is a problem when I cast std::function<>* to void*, seems the std::function<>* is destroyed when cast to void*.

Below is the test code.

#include <iostream>
#include <functional>

class TfLight {
 public:
  void print(int a) {
    std::cout << "TfLight::print " << a << std::endl;
  }
};

class Server {
 public:
  void run(int a) {
    std::function<void(int)>* func = reinterpret_cast<std::function<void(int)>*>(ptr);
    std::cout << func << std::endl;
    (*func)(a);
  }
  
  void register(std::function<void(int)> tf) {
    std::cout << (&tf) << std::endl;
    // f = tf;
    setPtr(&tf);
  }
  
  void setPtr(void* p) {
    ptr = p;
  }
  
  std::function<void(int)> f;
  void* ptr;
};

int main()
{
    TfLight* tf = new TfLight();
    Server* server = new Server();
    server->register(std::bind(&TfLight::print, tf, std::placeholders::_1));
    server->run(3333);
    
    delete server;
    delete tf;
}

When I use a global variable to holder "std::function<void(int)>", it can be called normally. How can I deal with this problem?

But there is a problem when I cast std::function<>* to void*, seems the std::function<>* is destroyed when cast to void*

Upvotes: 0

Views: 198

Answers (1)

MSalters
MSalters

Reputation: 179799

std::bind is a function. It's not on the stack or the heap.

Its return value is a temporary object, and has the usual lifetime of temporaries. That's not the problem here; the bind return value is stored in the std::function passed to register.

In register, again the normal C++ rules are followed. std::function<void(int)> tf) is a function argument, so &tf remains valid for the duration of the call. As soon as register returns, tf ceases to exist. The commented-out code is correct; you should have copied it to Server::f.

Since you have Server::f, the void* Server::ptr seems entirely pointless. Yes, you can set ptr to &f, but why?

Upvotes: 8

Related Questions