2011-04-05 32 views
4

下面的代码编译和运行在标准Linux:机器人+并行线程+ C++ = SIGSEGV

#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()看来,在我的代码中只是存在这个调用,而不介意执行,导致我的编程陷入错误。有任何想法吗?

+1

你的错误检查是错误的。 pthread_create&join将在成功时返回0,否则为表示错误的整数。你可能因为某个原因失败,不知道它。 – Duck 2011-04-05 03:48:51

+0

是的,好眼睛。我纠正了这个帖子,但核心问题仍然存在。谢谢! – awm129 2011-04-05 04:00:53

回答

1

这个问题似乎是iostream和pthread的结合。我用printf()替换了所有的cout,删除了using子句,并删除了iostream头。代码编译并在设备上运行时没有问题。我想知道这是Google应该注意的事情吗?

最后的(工作)的代码如下所示:

#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; 
} 
6

它可能不是这一点,但尝试使通过并行线程调用的函数创建一个普通的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) 
+0

'[basic.compound]'和'[expr.unary.op]'判定指向静态成员的指针可以与指向自由函数的指针互换。这并不完全排除与'extern“C”调用约定的不兼容性,但您需要一些其他特定于实现的修补程序来更改调用约定。 – 2011-04-05 04:44:42

+0

@Ben:C++函数。不是C函数(又名extern“C”)。请注意,pthread是一个C库,因此在它接收的指针上使用“C”调用约定。一旦进入start_the_thread()函数,我们当然可以正常地调用静态成员函数。 – 2011-04-05 04:48:01

+1

@Martin:正确,语言链接是函数指针类型的一部分。但是它应用了'extern'C''连接,而不是在课堂外部移动功能,修复了类型。由于它是一种类型不匹配,编译器应该抛出一个错误 - 函数指针永远不会被隐式转换。 – 2011-04-05 04:52:36