Function Pointer in Class (SOLVED - array overrun!)

I've got a question about classes that contain a function pointer. What is their initial value when the class is created? Here's an extract of my code:

typedef void (* DetectionCallback) ( ObserverDetection* ); 

class ObserverDetection
{
public:
	ObserverDetection( byte pin );
    void Process();
	void setDetectionCallback( DetectionCallback callback );

private:
	byte _pin;
	DetectionCallback _callback;
};

ObserverDetection::ObserverDetection( byte pin )
{
	_pin = pin;
	pinMode(_pin, INPUT);

	_callback = NULL; // problem occurs whether this line is present or not
}

void ObserverDetection::Process()
{
// doCallback gets set by logic within Process which I'm not showing
// but the problem is in this next line, with the test for whether or
// not _callback is defined or NULL/0. Regardless of whether or not
// I call setDetectionCallback(), _callback is always nonzero.
// 
        if( doCallback && (_callback != 0) ) _callback(this);
}

void ObserverDetection::setDetectionCallback( DetectionCallback callback )
{
	_callback = callback;
}

It's easy enough to put another field in the class (e.g., _callbackDefined) to flag whether or not one has been defined, and then test for that. But the approach of testing the value of _callback directly was something I saw in the Time library, and it works perfectly there. However, in the Time library the function pointer is a static variable within the cpp file, not a class field.

What's the reason for the difference in behavior?

Moderator edit: [code] ... [/code] tags added. (Nick Gammon)

Read this before posting a programming question

I added code tags for you.

Where is ObserverDetection instantiated?

Can you make a complete piece of code that demonstrates the problem?

Mark, everything looks alright to me with your code, at least this compiles and runs properly in gcc 3.4.4 (only slightly tweaked marked "jcc" for compatibility)

/*
 * Observer.cpp
 *
 *  Created on: Jan 26, 2013
 *      Author: John
 */
#include <iostream>
using namespace std;

class ObserverDetection;
typedef char byte;

typedef void (* DetectionCallback) ( ObserverDetection* );

class ObserverDetection
{
public:
   ObserverDetection( byte pin );
    void Process();
   void setDetectionCallback( DetectionCallback callback );

// private:
   byte _pin;
   DetectionCallback _callback;
};

ObserverDetection::ObserverDetection( byte pin )
{
   _pin = pin;
   // pinMode(_pin, INPUT);    <<<<<< jcc removed, shouldn't be here anyway, others will tell you why
   _callback = NULL; // problem occurs whether this line is present or not  
}

void ObserverDetection::Process()
{
// doCallback gets set by logic within Process which I'm not showing
// but the problem is in this next line, with the test for whether or
// not _callback is defined or NULL/0. Regardless of whether or not
// I call setDetectionCallback(), _callback is always nonzero.
//
	cout << "ObserverDetection on pin " << int(_pin) << " is processing" << endl;
        if( _callback != 0 ) _callback(this);    // <<<<<<<<< jcc skipped doCallback
}

void ObserverDetection::setDetectionCallback( DetectionCallback callback )
{
   _callback = callback;
}


void testCallback( ObserverDetection * d){
	cout << "Got here to testCallback from ObserverDection on pin " << int( d->_pin) << endl;
}


int main(){
	cout << "Start" << endl;
	ObserverDetection o1(7);
	ObserverDetection o2(8);

	o1.Process();
	o2.Process();

	o1.setDetectionCallback(testCallback);
	o1.Process();
	o2.Process();
}

Output:

Start
ObserverDetection on pin 7 is processing
ObserverDetection on pin 8 is processing
ObserverDetection on pin 7 is processing
Got here to testCallback from ObserverDection on pin 7
ObserverDetection on pin 8 is processing

Forgot to note, I had to forward-declare

class ObserverDetection;
typedef void (* DetectionCallback) ( ObserverDetection* );
class ObserverDetection
{...}

slightly surprised Arduino compiler did not complain at you for that...

John & Nick,

Thanks for the quick feedback, and cross-compiling the code for me :).

I'm embarrassed to have to report the problem was, as is almost always the case, the boob behind the keyboard.

One of the things I didn't show in the code extract was that there is a private unsigned long array located immediately before the private callback pointer field. My program logic triggered an array overrun condition (i.e., I ended up writing past the end of the array). Which naturally caused all sorts of bizarre behavior, including changing the callback pointer value (plus some other private values, too).

I'm too used to programming in c#, where a mistake like that would cause the program to blow up when it executed.

LOL, no problem-- glad you found the bug!!

Cheers,
John

Yes with OO and c++ we have much, much fancier ways to
goto:

:slight_smile: