簡體   English   中英

如果不包含 pthread,為什么 GCC 的線程標准庫實現會拋出異常?

[英]Why does GCC's threading standard library implementation throw exceptions if you don't include pthread?

當我編寫使用例如std::promise的代碼時,並且我沒有在 GCC 中包含 PThread 庫時,我得到一個異常拋出而不是一個 Z3175B426046787EECE2377387340B 錯誤。 例如:

void product(std::promise<int> intPromise, int a, int b)
{
    intPromise.set_value(a * b);
}
int main()
{
    int a = 20;
    int b = 10;
    std::promise<int> prodPromise;
    std::future<int> prodResult = prodPromise.get_future();
    product(std::move(prodPromise), a, b);
    std::cout << "20*10= " << prodResult.get() << std::endl;
}

如果我在沒有-pthread的情況下編譯此代碼,則會引發以下異常:

terminate called after throwing an instance of 'std::system_error'
  what():  Unknown error -1
Aborted (core dumped)

如果std::promise在內部使用pthread庫,那么如果我沒有將-pthread命令行選項提供給g++ ,它應該會引發鏈接錯誤。 但它的編譯沒有任何錯誤,並且在運行時我遇到了上述問題。

原因是libstdc++使用了所謂的弱引用

我們可以輕松追蹤您的特定代碼示例引發異常的原因。 set_value()調用std::call_once function 在其實現中具有以下行*

int e = gthread_once(&once.M_once, &once_proxy);

其中gthread_once

static inline int gthread_once(gthread_once_t *once, void (*func)(void))
{
  if (gthread_active_p())
    return ...
  else
    return -1;
}

gthread_active_p返回false ,這就是gthread_once返回-1的原因,這在異常字符串中有所提及。

現在讓我們一下gthread_active_p

static __typeof(pthread_key_create) gthrw_pthread_key_create
    __attribute__ ((weakref("__pthread_key_create")));

static inline int gthread_active_p(void)
{
  static void *const gthread_active_ptr = (void *)&gthrw_pthread_key_create;
  return gthread_active_ptr != 0;
}

gthrw_pthread_key_create是對__pthread_key_create弱引用 如果 linker 沒有找到符號__pthread_key_create ,則&gthrw_pthread_key_create將是 null 指針,如果找到__pthread_key_create ,則gthrw_pthread_key_create將為它的別名。 __pthread_key_createpthreads庫導出。

標准庫源代碼還包含以下注釋:

對於多線程程序,它肯定必須使用的唯一東西是pthread_create 但是,可能有其他庫使用自己的定義攔截pthread_create以出於某種目的包裝pthreads功能。 在這些情況下,定義pthread_create可能並不一定意味着libpthread實際上已鏈接。

對於 GNU C 庫,我們可以使用已知的內部名稱。 這在 ABI 中始終可用,但沒有其他庫會定義它。 這是理想的,因為任何公共pthread function 都可能像pthread_create might be一樣被攔截。 __pthread_key_create是一個“內部”實現符號,但它是公共導出 ABI 的一部分。 此外,它是 static libpthread.a始終在使用pthread_create時鏈接的符號之一,因此在任何靜態鏈接的多線程程序中都不存在誤報結果的危險。


*刪除了一些下划線並擴展了宏以提高可讀性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM