0

The idea is to call different functions based on their index in table. But line 27 generates the runtime error (( I tried to fix but didn't succeed ((( Here's the simplified code:

#include <iostream>

void f1 (void) {
  std::cout << "f1" << "\n";
}

void f2 (void) {
  std::cout << "f2" << "\n";
}

typedef void (*fPtr[3])(void); // simple "[]" instead of "[3]" gets the compile error

class modeChanger {
  public:
    modeChanger (fPtr funcArray);
    void op ();
  private:
    fPtr *_funcArray;
};

modeChanger::modeChanger (fPtr funcArray) {
  _funcArray = (fPtr *) funcArray;
}

void modeChanger::op () {
  (*_funcArray[0])();
  (*_funcArray[1])(); // Line 27: this line generates a runtime error! Just comment it to get all work
}

void (*modeFuncArray[])(void) = {f1, f2, f2};

modeChanger *mode = new modeChanger (modeFuncArray);

int main() {
    (*modeFuncArray[1])(); // Works fine

    mode->op(); // generates a runtime error
    return 0;
}

This works good:

(*_funcArray[0])();

as well as this:

(*modeFuncArray[1])();

but this generates a runtime error...

(*_funcArray[1])(); 

Seems that incrementing of _funcArray is incorrect for some reason.

4
  • 8
    Firsst thing to do is to not try to shut up compiler warnings by using casts... those warnings are telling you something. (referring to _funcArray = (fPtr *) funcArray;) Commented Apr 20, 2018 at 13:26
  • 2
    May I suggest you stop using raw function pointers in C++? Use std::function instead. That will make much of your code simpler. Then if you use a standard container like std::vector or std::array then you simplify even further. Simple code have less chance of errors or problems. Commented Apr 20, 2018 at 13:27
  • Once you've done as M.M says, a read of ericlippert.com/2014/03/05/how-to-debug-small-programs will be invaluable. Commented Apr 20, 2018 at 13:28
  • 1
    Regarding the comment by @M.M, almost always when you need to use a C-style cast in C++, you're most likely doing something wrong. Commented Apr 20, 2018 at 13:31

3 Answers 3

3

fPtr *_funcArray; this is the pointer to array, not an array of pointers. You suppressed warnings with help of type casts. See bellow the fixed code.

#include <iostream>

void f1 (void) {
  std::cout << "f1" << "\n";
}

void f2 (void) {
  std::cout << "f2" << "\n";
}

typedef void (*fPtr)(void);

class modeChanger {
  public:
    modeChanger (fPtr *funcArray);
    void op ();
  private:
    fPtr *_funcArray;
};

modeChanger::modeChanger (fPtr *funcArray) {
  _funcArray = funcArray;
}

void modeChanger::op () {
  (*_funcArray[0])();
  (*_funcArray[1])(); // Line 27: this line generates a runtime error! Just comment it to get all work
}

void (*modeFuncArray[])(void) = {f1, f2, f2};

modeChanger *mode = new modeChanger (modeFuncArray);

int main() {
    (*modeFuncArray[1])(); // Works fine

    mode->op(); // generates a runtime error
    return 0;
}
Sign up to request clarification or add additional context in comments.

2 Comments

Why not change the declaration of modeFuncArray to use the fPtr type instead as well? Like fPtr modeFuncArray[] = { ... }
@Someprogrammerdude It is possible too, in this case OP should copy an array. Or OP can left a pointer to array, and then he should dereference a pointer before accessing array elements. All these cases are terrible.
2

Applying @Someprogrammerdude's advice:

#include <iostream>
#include <array>
#include <functional>

void f1 (void) {
  std::cout << "f1" << "\n";
}

void f2 (void) {
  std::cout << "f2" << "\n";
}

using fPtr = std::function<void()>;
using fPtrs = std::array<fPtr, 3>;

class modeChanger {
  public:
    modeChanger (fPtrs funcArray);
    void op ();
  private:
    fPtrs _funcArray;
};

modeChanger::modeChanger (fPtrs funcArray) : _funcArray(funcArray) { }

void modeChanger::op () {
  _funcArray[0]();
  _funcArray[1]();
}   

int main() {
    fPtrs modeFuncArray = {f1, f2, f2};
    modeChanger mode(modeFuncArray);
    modeFuncArray[1]();

    mode.op(); 
    return 0;
}

And thus instead of "hard to declare" C types, we have things as easy as int, and all is well.

Comments

0

as you use c++, you should use c++ features and not C, you should use <functional>

#include <iostream>
#include <functional>
void f1(void) {
    std::cout << "f1" << "\n";
}

void f2(void) {
    std::cout << "f2" << "\n";
}

typedef void(*fPtr[3])(void); // simple "[]" gets the compile error

class modeChanger {
public:
    modeChanger(std::function<void(void)>* funcArray);
    void op();
private:
    std::function<void(void)> * _funcArray;
};

modeChanger::modeChanger(std::function<void(void)>* funcArray) {
    _funcArray = funcArray;
}

void modeChanger::op() {
    _funcArray[0]();
    _funcArray[1](); // this line generates a runtime error! Just comment it to get all work
}

std::function<void(void)>  modeFuncArray[]  = { f1, f2, f2 };

modeChanger *mode = new modeChanger(modeFuncArray);

int main() {
    modeFuncArray[1](); // Works fine

    mode->op(); // generates a runtime error
    return 0;
}

2 Comments

This is a mess IMHO. You say not to "use C features" but your code is full of pointers.
@M.M i wanted to keep the origin code and format for the OP, so he will see the difference of using it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.