![](/img/trans.png)
[英]If you're in the “we don't use exceptions” camp, then how do you use the standard library?
[英]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 *)>hrw_pthread_key_create;
return gthread_active_ptr != 0;
}
gthrw_pthread_key_create
是對__pthread_key_create
的弱引用。 如果 linker 沒有找到符號__pthread_key_create
,則>hrw_pthread_key_create
將是 null 指針,如果找到__pthread_key_create
,則gthrw_pthread_key_create
將為它的別名。 __pthread_key_create
由pthreads
庫導出。
標准庫源代碼還包含以下注釋:
對於多線程程序,它肯定必須使用的唯一東西是
pthread_create
。 但是,可能有其他庫使用自己的定義攔截pthread_create
以出於某種目的包裝pthreads
功能。 在這些情況下,定義pthread_create
可能並不一定意味着libpthread
實際上已鏈接。對於 GNU C 庫,我們可以使用已知的內部名稱。 這在 ABI 中始終可用,但沒有其他庫會定義它。 這是理想的,因為任何公共
pthread
function 都可能像pthread_create might be
一樣被攔截。__pthread_key_create
是一個“內部”實現符號,但它是公共導出 ABI 的一部分。 此外,它是 staticlibpthread.a
始終在使用pthread_create
時鏈接的符號之一,因此在任何靜態鏈接的多線程程序中都不存在誤報結果的危險。
*刪除了一些下划線並擴展了宏以提高可讀性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.