Czemu wątek dostaje SIGABRT?

0

Chciałem ponaśmiewać się z debila, a wygląda, że sam wchodzę w rolę debila ;P sigh

Chciałem zrobić program liczący sumę cyfr danej liczby na wątkach. Chciałem to zrobić również jako ćwiczenie na wątki, bo pierwszy raz w życiu korzystam z nagłówka <thread>.

 #include <iostream>
#include <string>
#include <sstream>
#include <thread>
#include <future>
#include <utility>
#include <stdexcept>
#include <cstdint>
using namespace std;

void sum_of_digits(string::const_iterator it, string::const_iterator jt, promise<uint_fast64_t> res)
{
	if(jt - it == 1) {
		uint_fast64_t i; stringstream {string{it, jt}} >> i;
		res.set_value_at_thread_exit(i);
		return;
	}
	
	if(jt - it == 2) {
		uint_fast64_t i; stringstream {string{it, it+1}} >> i;
		uint_fast64_t j; stringstream {string{jt-1, jt}} >> j;
		res.set_value_at_thread_exit(i+j);
		return;
	}
	
	if(jt - it > 2) {
		promise<uint_fast64_t> leftmost_range; promise<uint_fast64_t> rightmost_range;
		auto lrf = leftmost_range.get_future(); auto rrf = rightmost_range.get_future();
		thread lrt(sum_of_digits, it, it + (jt - it) / 2, move(leftmost_range));
		thread rrt(sum_of_digits, it + (jt - it) / 2, jt, move(rightmost_range));
		lrf.wait(); rrf.wait();
		res.set_value_at_thread_exit(lrf.get() + rrf.get());
		return;
	}
}

int main()
{
	string numb; getline(cin, numb);
	
	while(numb.size() > 1) {
		promise<uint_fast64_t> pr; auto fut = pr.get_future();
		thread thr(sum_of_digits, numb.begin(), numb.end(), move(pr));
		fut.wait(); auto res = fut.get();
		cout << res << '\n';
		stringstream ss; ss << res; numb = ss.str();
	}
}

Niestety, leci SIGABRT. Debugger wykazał, że leci w linii 33, tj. return; funkcji sum_of_digits dla przypadku, gdy jt-it>2. Nie rozumiem tego, bo jeśli dobrze rozumiem debuggera, to res.set_value_at_thread_exit(lrf.get() + rrf.get()); działa poprawnie. Mało tego: wątki dla przypadku, gdy jt - it == 2 działają, i zakańczają się poprawnie.

Gdzie jest moje idioctwo?

0

"Chciałem zrobić program liczący sumę cyfr danej liczby na wątkach."
Złożoność problemu to:
O(\log_{10} n)

gdzie n - to dana liczba. Dla wszystkich praktycznych przypadków podstawowych typów w C/C++ oznacza to co najwyżej kilkadziesiąt kroków. Skąd w ogóle pomysł używania wątków do takiego problemu?

2

Stworzyłeś obiekty std::thread, ale nie wywołałeś ani join() ani detach().

0

@twonek

Rzeczywiście, join() rozwiązuje sprawę. Dzięki.

Jeśli mam być szczery, nie rozumiem nadal dlaczego niewywołanie join() to aż SIGABRT. http://en.cppreference.com/w/cpp/thread/thread/join – nic tu nie ma o OBOWIĄZKU wywołania join(). Myślałem, że join() służy wyłącznie do tego, jeśli trzeba wstrzymać wykonywanie wątku-rodzica aż to końca działania wątku-dziecka, a w najgorszym razie, że powstanie wątek zombie, który zostanie posprzątany na koniec działania programu.

1

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

Destruktor wywala jeśli w momencie wywołania wątek jest nadal joinable, czyli nie wykonano join() lub detach() (lub nie wykonano na nim move).

1 użytkowników online, w tym zalogowanych: 0, gości: 1