if(mySharedPtr) causes Signal 11?

0

Somehow, accessing a shared_ptr without dereferencing it is causing a Signal 11 (SIGSEGV) on Android.

I have a run() function in A that acquires a lock for it's instance of B and calls B::top(). There is only one instance of A. A has other public methods that other threads might call to modify mB (thus the mutex), but they are not being called by anything yet.

LogCat Error:

04-17 15:15:16.903: A/libc(11591): Fatal signal 11 (SIGSEGV) at 0x00000024 (code=1)

In class A:

std::thread mControllerThread;
std::mutex mBMutex;
shared_ptr<B> mB;

A() {  
    mB.reset( new B() ); 
    mControllerThread = std::thread( std::bind(&A::run, this) );       
}

//...

void run() {
    std::unique_lock<std::mutex > lk(mBMutex);
    shared_ptr<const Event> event = mB->top(B::Scope::FUTURE);
}

In class B:

shared_ptr<EventHeap> mFuture;

B() {
    mFuture.reset( new EventHeap() );
}

//...

shared_ptr<const Event> top(Scope scope, int mask=EVENT_MASK_SUPPORTED) const {
    shared_ptr<const Event> event;

    if(scope == Scope::PAST) {
        //...
    } else if(scope == Scope::FUTURE) {
        LOGD(LOG_TAG, "Testing mFuture ptr");
        // Fails here with any of these versions
        if(mFuture) {
        // if(mFuture.get() != NULL) {
        // if(mFuture != nullptr) {
            LOGD(LOG_TAG, "Getting top from FUTURE");
            event = mFuture->top(mask);
        } else {
            LOGE(LOG_TAG, "mFuture is null");
        }
    }
    return event;
}

So how can accessing a smart pointer without dereferencing it possibly cause a segfault? Thanks!

c++
android-ndk
segmentation-fault
smart-pointers
asked on Stack Overflow Apr 18, 2014 by mxdubois • edited Apr 18, 2014 by mxdubois

1 Answer

0

The statement you point test if the shared_ptr is initialized with a non-null pointer.

if(mFuture) // can be seen as if(mFuture.privateMember_Ptr != nullptr)

It is pretty clear that the pointer itself is not dereferenced, but the value of the pointer is accessed. So this memory location seems invalid. Now where is this memory location? It is part of mFuture which is itself part of B. Let's rewrite the mFuture to show what we really dereference:

if(this->mFuture.privateMember_Ptr != nullptr)

It seems that "this" is invalid, you can start by printing it in the top method, and "unwind" the stack with the same debugging. Looking at the source, "this" should correspond to mB in class A. So you can print mB in A::run() before calling B::top(). mB is initialized in A's ctor with a "new B()". Do you check somewhere that this memory allocation succeed? (exceptions are disabled by default on Android AFAIK, so new can return nullptr)

answered on Stack Overflow Apr 19, 2014 by Joky

User contributions licensed under CC BY-SA 3.0