Pages: [1]   Go Down
Author Topic: Function Pointer in Class (SOLVED - array overrun!)  (Read 716 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 1
Posts: 38
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

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)
« Last Edit: January 26, 2013, 09:55:53 pm by Mark Olbert » Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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?

Logged

Temple, Texas
Offline Offline
Sr. Member
****
Karma: 14
Posts: 360
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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)
Code:
/*
 * 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:
Code:
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
Logged

Temple, Texas
Offline Offline
Sr. Member
****
Karma: 14
Posts: 360
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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...
Logged

0
Offline Offline
Newbie
*
Karma: 1
Posts: 38
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

John & Nick,

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

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.
Logged

Temple, Texas
Offline Offline
Sr. Member
****
Karma: 14
Posts: 360
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Cheers,
John
Logged

Temple, Texas
Offline Offline
Sr. Member
****
Karma: 14
Posts: 360
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

naturally caused all sorts of bizarre behavior, including changing the callback pointer value (plus some other private values, too).

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

smiley
Logged

Pages: [1]   Go Up
Jump to: