android + pthread + c ++ = SIGSEGV

时间:2011-04-05 03:36:07

标签: c++ android pthreads

以下代码在标准linux上编译并运行:

#include <iostream>
#include <pthread.h>

using namespace std;

class Foo
{
    public:
        Foo();
        void go_thread();
        void stop_thread();
    private:
        static void* worker( void* param );
        pthread_t m_pt;
};

Foo::Foo()
{
    m_pt = 0;
}

void Foo::go_thread()
{
    int success = pthread_create( &m_pt, NULL, worker, static_cast<void*>(this) );

    if( success == 0 )
    {
        cout << "thread started" << endl;
    }
}

void Foo::stop_thread()
{
    int success = pthread_join( m_pt, NULL );

    if( success == 0 )
    {
        cout << "thread stopped" << endl;
    }
}

void* Foo::worker( void* p )
{
    cout << "thread running" << endl;
    return 0;
}

int main()
{
    Foo f;
    f.go_thread();
    f.stop_thread();
    return 0;
}

并生成以下输出:

$ ./a.out
thread started
thread running
thread stopped
$

此代码也使用Android NDK(r5b)构建。但是,当我adb将生成的可执行文件推送到设备并运行它时,我会在main()运行之前得到一个SIGSEGV。我把这个问题分离到pthread_create()似乎在我的代码中只存在这个调用,从不介意执行,导致我的编程出错。有什么想法吗?

2 个答案:

答案 0 :(得分:6)

可能不是这样但是尝试使pthread调用的函数创建一个普通的c函数(即声明它为extern“C”)而不是静态成员函数:

这是因为从技术上讲,静态成员的调用约定可能与C库pthread使用的C调用约定不同(虽然很多时候它们是相同的(这就是为什么它在你的linux上工作)在我看来,这不值得移植风险)。

extern "C" void* start_the_thread(void*);

void* start_the_thread(void* data)
{
    Foo*  theObject = static_cast<Foo*>(data);
    // In Java if your Foo had been derived from Runable
    // This is s where theObject->run() would have been called.
    return Foo::worker(data);
}

int success = pthread_create( &m_pt, NULL, start_the_thread, static_cast<void*>(this)

答案 1 :(得分:1)

问题似乎是将iostream与pthread结合起来。我经历了用printf()替换所有couts,删除了using子句,并删除了iostream头。编译并运行的代码在设备上没有问题。我想知道这是否应该让谷歌意识到这一点?

最终(工作)代码如下:

#include <pthread.h>
#include <stdio.h>

class Foo
{
    public:
        Foo();
        void go_thread();
        void stop_thread();
    private:
        static void* worker( void* param );
        pthread_t m_pt;
};

Foo::Foo()
{
    m_pt = 0;
}

void Foo::go_thread()
{
    int success = pthread_create( &m_pt, NULL, worker, static_cast<void*>(this) );

    if( success == 0 )
    {
        printf( "thread started\n" );
    }
}

void Foo::stop_thread()
{
    int success = pthread_join( m_pt, NULL );

    if( success == 0 )
    {
        printf( "thread stopped\n" );
    }
}

void* Foo::worker( void* p )
{
    printf( "thread running\n" );
    return 0;
}

int main()
{
    Foo f;
    f.go_thread();
    f.stop_thread();
    return 0;
}