2011-04-05 31 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