tags:

views:

63

answers:

4

I have a class, in which i declare a static function. I register this function as the callback function for another library. Now, inside this function, i dereference the callback data to the class pointer and invoke a particular non-static member.

The invocation succeeds and the control comes into the non-static member function. But inside this function at the point where i access a member variable of the same class, i get a segmentation fault. This is strange. Can anybody help me with the possible mistake i have made and the solution?

Here is how the code looks like.

class test
{
   int count;
   int callback(const char * a, const char *b)
   {
      print(a);
      print(b);
      count++; //// HERE IS WHERE I GET THE SEGMENTATION FAULT
   }

   public:
   static int callbackwrapper(const char*a, const char *b, void *ptr)
   {
      test *p = (test *)ptr; 
      p->callback(a, b);
   }

   test():count(0) {}
   ~test() {}
   Register()
   {
      registercallback(callbackwrapper);
   }
}
+2  A: 

Stop using void*s. You will get yourself into a lot of trouble.

Chances are you're calling callback() on an invalid object. I can't tell from the example you gave, but that's what it seems like to me. I would need to see registercallback()'s implementation to be sure, but I note that callbackwrapper() is NOT a static function, and therefore calling it as if it were a static function (which I suspect may be the case) will wreak all sorts of havoc.

Shirik
+1 for diagnosis of the lack of `static`
Billy ONeal
A: 

We'd need to see what "registercallback" does. Sounds like it's passing you a bad pointer, or a pointer to something that isn't actually a test.

Also, callbackwrapper looks like it ought to be static. registercallback doesn't seem to be declared in class test, and no other class should be taking pointers to instance methods of test.

cHao
+2  A: 

The ptr passed to callackwrapper is most likely an invalid pointer or not an object of the class test. The invocation still succeeds because as long as you don't access a member variable, a class method is the same as a normal C++ function. Where you access count is when you actually dereference the object, hence the segmentation fault.

casablanca
A: 
int callbackwrapper(const char*a, const char *b, void *ptr)
{
  test *p = (test *)ptr; 
  p->callback(a, b);
}

is a member function. That member function is looking for a reference to the object to which it belongs. That is, the function above becomes something like this under the covers:

int callbackwrapper(test* this, const char*a, const char *b, void *ptr)
{
  test *p = (test *)ptr; 
  p->callback(a, b);
}

Most likely registercallback is not expecting a member function here.

You can solve this by making callbackwrapper a static member function:

static int callbackwrapper(const char*a, const char *b, void *ptr)
{
  test *p = (test *)ptr; 
  p->callback(a, b);
}

Also, don't forget: If you are interfacing with a C library, and that's why you're needing the callback, do keep in mind that functions to be called from C need to be declared extern "C", which would force you to move that function out of the class, and make it

extern "C" int callbackwrapper(const char*a, const char *b, void *ptr)
{
  test *p = (test *)ptr; 
  p->callback(a, b);
}
Billy ONeal