ubuntuusers.de

C++11 Concurrency Problem

Status: Gelöst | Ubuntu-Version: Ubuntu 13.10 (Saucy Salamander)
Antworten |

-Mesut-

Anmeldungsdatum:
20. November 2013

Beiträge: 8

Hi,

wenn ich dieses Programmbeispiel bei mir übersetze

1
g++ -std=c++11 async1.cpp -o ex1.o

Und dann ausführe, bekomme ich folgenden Fehler:

1
2
3
4
starting func1() in background and func2() in foreground:
++++++++++terminate called after throwing an instance of 'std::system_error'
  what():  Unknown error -1
Aborted (core dumped)

Laut dem Buch dürfte hier aber auf "gar keinen" Fall ein Fehler auftreten. Woran könnte das bei mir liegen?

Benutze:

1
gcc version 4.8.1 (Ubuntu/Linaro 4.8.1-10ubuntu8) 

Dee Team-Icon

Avatar von Dee

Anmeldungsdatum:
9. Februar 2006

Beiträge: 20095

Wohnort: Schwabenländle

Hi und willkommen im Forum.

ich habe den gleichen Fehler mit gcc4.6. Wenn Du den Aufruf von func2() auskommentierst, kommt der Fehler sogar noch schneller. Aber: Es tritt nur temporär auf. Das heißt, ich habe mehrfach kompiliert(ausgeführt und manchmal ging es ohne Probleme durch.

Interessanterweise sehe ich auch keine Ausgabe des '.', sondern nur das '+' zehnmal. Ohne get() tritt der Fehler auch nicht auf.

Ich habe versucht mit gdb reinzuschauen, aber der Ort des Absturzes ist irgendwo in der libstdc++.so.6 in einem Future-Kontext.

Mal schauen, ob jemand noch mehr draus ablesen kann.

Gruß Dee

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13204

Ich habe g++ 4.8.2 unter Cygwin x64 und kann den Fehler nicht reproduzieren (50 Durchläufe schon).

Pack doch mal einen try-catch-Block für den angegebenen std::system_error in func1 und in main und gibt mal die Fehlermeldung aus.

Gibt der Coredump irgendwelche Informationen preis? Du musst aber wohl mit Option -g übersetzen, um die Debuginfos zu bekommen. Falls Du keinen core bekommst, schau mal auf ulimit -a. Kann sein, dass da 0 als Größe angegeben ist.

Ciao

robert

-Mesut-

(Themenstarter)

Anmeldungsdatum:
20. November 2013

Beiträge: 8

Hi,

danke für eure Mühe. Ich werd mal versuchen ein bisschen zu debuggen, bin aber kein Held auf dem Gebiet 😢

Gruß

Dee Team-Icon

Avatar von Dee

Anmeldungsdatum:
9. Februar 2006

Beiträge: 20095

Wohnort: Schwabenländle

Gibt der Coredump irgendwelche Informationen preis?

Hier erstmal der Stack

Program received signal SIGABRT, Aborted.
0x00007ffff753a425 in raise () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) where
#0  0x00007ffff753a425 in raise () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x00007ffff753db8b in abort () from /lib/x86_64-linux-gnu/libc.so.6
#2  0x00007ffff7b9169d in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007ffff7b8f846 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007ffff7b8f873 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007ffff7b8f96e in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007ffff7b3cc8e in std::__throw_system_error(int) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7  0x000000000040277c in std::call_once<void (std::__future_base::_State_base::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>&, bool&), std::__future_base::_State_base* const, std::reference_wrapper<std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()> >, std::reference_wrapper<bool> >(std::once_flag&, void (std::__future_base::_State_base::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>&, bool&), std::__future_base::_State_base* const&&, std::reference_wrapper<std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()> >&&, std::reference_wrapper<bool>&&) (__once=..., __f=
    @0x7fffffffdf40: (void (std::__future_base::_State_base::*)(std::__future_base::_State_base * const, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>()> &, bool &)) 0x4022da <std::__future_base::_State_base::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>&, bool&)>) at /usr/include/c++/4.6/mutex:819
#8  0x0000000000402291 in std::__future_base::_State_base::_M_set_result(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>, bool) (this=0x611030, __res=..., __ignore_failure=true)
    at /usr/include/c++/4.6/future:337
#9  0x0000000000408187 in std::__future_base::_Deferred_state<int>::_M_run_deferred (this=0x611030)
    at /usr/include/c++/4.6/future:1320
#10 0x000000000040213c in std::__future_base::_State_base::wait (this=0x611030) at /usr/include/c++/4.6/future:305
#11 0x00000000004037b5 in std::__basic_future<int>::_M_get_result (this=0x7fffffffe1a0) at /usr/include/c++/4.6/future:548
#12 0x0000000000402b86 in std::future<int>::get (this=0x7fffffffe1a0) at /usr/include/c++/4.6/future:627
#13 0x0000000000401ba2 in main () at async.cpp:45

Falls Du keinen core bekommst, schau mal auf ulimit -a.

Du solltest dann noch sagen, wie man das ändert, falls dort bei "core size" eine 0 angegeben ist. ☺ (Antwort: Es geht z.B. mit 'ulimit -c 1000000'.)

Dann mal mit einem try-catch:

$ ./a.out
starting func1() in background and func2() in foreground:
++++++++++
Caught system_error with code "generic:-1" meaning "Unknown error -1".

result of func1()+func2(): 0

Also auch nicht sehr hilfreich.

Update: Aber wenn man etwas sucht, findet man die Lösung (erster Treffer der Suche. *g*): http://www.cplusplus.com/forum/beginner/115878/

$ g++ -std=c++11  -pthread async.cpp
$ ./a.out
starting func1() in background and func2() in foreground:
++++++++++..........
result of func1()+func2(): 89

Das "-pthread" ist also wichtig, damit überhaupt irgendwas mit mehr als einem Thread funktioniert.

Gruß Dee

-Mesut-

(Themenstarter)

Anmeldungsdatum:
20. November 2013

Beiträge: 8

Danke @Dee hat funktioniert. Hab dieselbe Ausgabe erhalten. Komisch aber, dass func1() nicht parallel ausgeführt wird, ansonsten wäre die Ausgabe irgendwie so ++..++...++....

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13204

Dee schrieb:

Gibt der Coredump irgendwelche Informationen preis?

Hier erstmal der Stack ...

Hmm...

Du solltest dann noch sagen, wie man das ändert, falls dort bei "core size" eine 0 angegeben ist. ☺ (Antwort: Es geht z.B. mit 'ulimit -c 1000000'.)

Das Lesen der Dokumentation ist ja nicht verboten. 😉

Update: Aber wenn man etwas sucht, findet man die Lösung (erster Treffer der Suche. *g*): http://www.cplusplus.com/forum/beginner/115878/

$ g++ -std=c++11  -pthread async.cpp
$ ./a.out
starting func1() in background and func2() in foreground:
++++++++++..........
result of func1()+func2(): 89

Das "-pthread" ist also wichtig, damit überhaupt irgendwas mit mehr als einem Thread funktioniert.

Das könnte man als Bug im betrachten: Durch die Auswahl des neuen Sprachstandards bekommt man ja auch die neuen Concurrency-Features. Naja, das ist ja auch immer noch ein wenig experimentell, und scheinbar haben sie das in meiner Version schon repariert - oder es liegt an Cygwin.

-Mesut- schrieb:

Danke @Dee hat funktioniert. Hab dieselbe Ausgabe erhalten. Komisch aber, dass func1() nicht parallel ausgeführt wird, ansonsten wäre die Ausgabe irgendwie so ++..++...++....

Das ist oft die Erwartung. Tatsächlich weisen aber Ausgabe wie die, die Du siehst, nicht unbedingt auf Probleme mit der Parallelität hin: der Scheduler ist frei darin, wie er die die Threads laufen lässt. In diesem Fall ist es allerdings noch anders:

Behaves the same as async(std::launch::async | std::launch::deferred, f, args...). In other words, f may be executed in another thread or it may be run synchronously when the resulting std::future is queried for a value.

http://en.cppreference.com/w/cpp/thread/async

Die Implementierung ist also frei, wie sie das macht - parallel oder on demand. Wenn Du explizit das Ausführungsmodell angibst (= eine Zeile änderst), kommt das Erwartete heraus:

1
    std::future<int> result1(std::async(std::launch::async, func1));

Man achte auf das erste Argument von std::async!

$ ./a
starting func1() in background and func2() in foreground:
+..+..+...+..+.+++++
result of func1()+func2(): 89 

Ciao

robert

-Mesut-

(Themenstarter)

Anmeldungsdatum:
20. November 2013

Beiträge: 8

Danke @robert hat funktioniert, die async Funktion wird irgendwie auch erst später im Kapitel ausführlich(er) erklärt 😳

Antworten |