Why Calling method through pure-virtual base class causing Seg Fault

Viewed 41

I have an interface defined by four abstract base class definitions.. In the implementaiton that I have now I get a segmentation fault while calling a concrete class method via the abstract class pointer.

Calling the concrete class method directly works fine.

    #include <iostream> 
    
    enum Result_t 
    { 
        SUCCESS            
    };
    
    class DataCallback {
        public:
        virtual Result_t Callback(int32_t data) = 0;
        virtual ~DataCallback(){}
    };
    
    class DataCallback_Actual {
        public:
            Result_t Callback(int32_t data)
            {
                std::cout << m_name << ": int data update: " << data << std::endl;
                return SUCCESS;
            }
    
            DataCallback_Actual(const std::string & name):
            m_name(name) 
            {
                std::cout << "constructor DataCallback_Actual::DataCallback_Actual(" << m_name << ") @ 0x" << std::hex << this << std::endl;
            }
    
        private:
            std::string m_name;
    };
    
    int main(int argv, char **argc)
    {
        // Create a pointer to the concrete class
        DataCallback_Actual * pDataCallbackTwo_A = new DataCallback_Actual(std::string("Object-Two-Int"));
DataCallback_Actual(std::string("Object-Two-Int")));
    
        DataCallback * pDataCallbackTwo = (DataCallback *) pDataCallbackTwo_A;
    
        //
        // TODO: Why does the first call work but I get a segfault 
        //       when calling through the abstract pointer...
        //
        pDataCallbackTwo_A->Callback(10);
        pDataCallbackTwo->Callback(12);
    }

When I execute the sample program the Callback() method works fine when using the _A pointer but I get a segmentation fault when calling through the base class pointer... The pointers are the same value.

A gdb sequence looks like..

Breakpoint 1, main (argv=21845, argc=0x7fffffffe1c0) at abstractFail.cpp:34
34  {
(gdb) n
36      DataCallback_Actual * pDataCallbackTwo_A = new DataCallback_Actual(std::string("Object-Two-Int"));
(gdb) n
constructor DataCallback_Actual::DataCallback_Actual(Object-Two-Int) @ 0x0x55555556aeb0
40      DataCallback * pDataCallbackTwo = (DataCallback *) pDataCallbackTwo_A;
(gdb) n
47      pDataCallbackTwo_A->Callback(10);
(gdb) p pDataCallbackTwo_A
$1 = (DataCallback_Actual *) 0x55555556aeb0
(gdb) p pDataCallbackTwo
$2 = (DataCallback *) 0x55555556aeb0
(gdb) n
Object-Two-Int: int data update: a
48      pDataCallbackTwo->Callback(12);
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x00005555555553f8 in main (argv=1, argc=0x7fffffffe308) at abstractFail.cpp:48
48      pDataCallbackTwo->Callback(12);
(gdb) 

I use the same pattern with another abstract/concrete class pair and it works fine. I don't like the fact that the two patterns are the same but one seg-faults and one does not.

1 Answers

Here's the culprit:

DataCallback *pDataCallbackTwo = (DataCallback *)pDataCallbackTwo_A

You reinterpret_cast pDataCallbackTwo_A into something that it is not and access it as-if it were, which causes undefined behavior.

Make DataCallback_Actual a type of DataCallback by inheriting from DataCallback:

class DataCallback_Actual : public DataCallback { 

and then you don't even need the cast:

DataCallback *pDataCallbackTwo = pDataCallbackTwo_A;
Related