2017-08-11 9 views
-1

J'ai un programme très simple:C++ 11: Clang sur Mac n'attrape pas les exceptions lancées par la fonction std :: thread?

#include <iostream> 
#include <string> 
#include <thread> 
using namespace std; 
struct N{ 
    string s; 
    N(){} 
    ~N(){cout<<"N dtor"<<endl;} 
}; 

void f(){ 
    N n; 
    throw 0; 
} 
int main(){ 
    try{ 
     thread a(f), b(f); 
     a.join(); 
     b.join(); 
    }catch(exception& e){ 
     cout<<e.what()<<endl; 
    } 
    return 0; 
} 

Sur mon environnement mac + clang, le résultat est en cours d'exécution:

libc++abi.dylib: terminating with uncaught exception of type int 
Abort trap: 6 

Il n'imprime pas le "N dtor" que je attendu. Donc ma question, si la fonction std :: thread renvoie une exception, comment l'attraper/gérer? Il n'y a aucune garantie que le code dans une fonction thread ne jette aucune exception.

Je l'ai essayé sur linux, et l'exception pourrait être pris et imprimer:

Enable multithreading to use std::thread: Operation not permitted 

Merci beaucoup.

+0

Si vous souhaitez transporter l'exception vers le thread appelant, utilisez 'std :: async'. – ecatmur

Répondre

2

Si une exception est levée dans un thread, elle doit être interceptée dans le même thread (ou pas du tout). Dans votre exemple, le bloc try peut capturer des exceptions spécifiquement à partir des tentatives de création ou de jointure des threads, mais pas d'exceptions provoquées par le code exécuté dans les threads.

Et si vous y réfléchissez, c'est comme ça que ça doit être. Votre exemple essaie de s'assurer que vous ne laissez pas le bloc try tant que les threads ne sont pas terminés, mais ce n'est pas quelque chose qui peut généralement être garanti. Même dans votre exemple, si les appels de jointure essayaient de lancer des exceptions qui provenaient du thread cible (ils ne le font pas, mais pour des raisons d'argument ...), vous n'atteindriez jamais l'appel join(b) et rien ne garantirait que vous êtes toujours dans le bloc try lorsque le fil de b lève son exception.

Le contrôle de flux pour un thread pour intercepter l'exception d'un autre ne fonctionne tout simplement pas. Si vous avez besoin de ce type de fonctionnalité, vous pouvez mettre un gestionnaire d'exception dans le thread de travail et le faire communiquer au thread principal en utilisant les mécanismes de communication inter-threads existants.