質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

排他制御

排他制御とは、特定のファイル・データへのアクセスや更新を制御することです。特にファイルやデータベースへ書き込みを行う際、データの整合性を保つため別のプログラムによる書き込みを一時的に制御することを指します。

マルチスレッド

マルチスレッドは、どのように機能がコンピュータによって実行したのかを、(一般的にはスレッドとして参照される)実行の複合的な共同作用するストリームへ区分することが出来ます。

Q&A

2回答

2126閲覧

非同期処理に対する返り値のバイトオーダーが崩れる問題について(ソースコードあり)

kkkmokotan

総合スコア45

C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

排他制御

排他制御とは、特定のファイル・データへのアクセスや更新を制御することです。特にファイルやデータベースへ書き込みを行う際、データの整合性を保つため別のプログラムによる書き込みを一時的に制御することを指します。

マルチスレッド

マルチスレッドは、どのように機能がコンピュータによって実行したのかを、(一般的にはスレッドとして参照される)実行の複合的な共同作用するストリームへ区分することが出来ます。

0グッド

0クリップ

投稿2017/06/20 09:21

編集2022/01/12 10:55

C言語にてこちらのサイトを参考にサーバへの非同期データ呼び出し処理を実装したいと思っています。中でも参考にしたのがOSSのスレッドプールで、このサイトにのっていたサンプルを参考にスレッドプールからデータ取得のAPI(ここではread_data())を呼び出し、非同期なデータ呼び出しプログラムを実装しました。しかし、結果の出力部分でバイトオーダが崩れる問題が発生してしまいます。結果の崩れ方は単純にバイトおーだが反転しているものや、そもそも値が崩れているものなど様々です。
read_data関数のエラーかと思いましたが、単一スレッドからread_data_indexesに対してread_dataを順番に呼び出した際にはこのようなことは起こらず、ちゃんと全ての結果が正しく確認できます。該当部分の自作クラスメソッド(クラス名はClientAPIです)を掲載いたします。

自身で色々調べたのですが、わからなかったためここに質問いたします。アドバイスをよろしくお願いいたします。(C言語の素人エンジニアなので書き方や使い方とうおかしいところがあるかもしれません。)

C++

1/*該当部分のコード*/ 2 vector<int> read_data_indexes = [0,1,2,3,4,5,6,7,8,9,10,11,12....200]; 3 vector<future<vector<struct data_list>>> *results; 4 ClientAPI *api = this; /*該当部分はClientAPI内部に実装されているので、clientAPI自身をthisで与える*/ 5 6 for(auto itr = read_data_indexes.begin(); itr != read_data_indexes.end(); ++itr) { 7 int tmp = *itr; 8 results->emplace_back( 9 this->pool->enqueue([tmp, api] { 10 struct data_list* result_list; 11 int result_num = 0; 12 vector<struct data_list> result_vector; 13 /* read_data(索引, 結果のリスト) にてサーバよりデータを取得、内部でホストオーダー<->ネットオーダー変換を実行 */ 14 result_num = api->read_data(tmp, result_list); 15 for(int i = 0; i < result_num; i++) { 16 return_vector.push_back(result_list[i]); 17 } 18 delete result_list; 19 return result_vector; 20 }) 21 ); 22 } 23 /*結果の出力*/ 24 for(auto && result: results) { 25 vector<struct data_list> tmp = result.get(); 26 for(auto itr = tmp.begin(); itr != tmp.end(); ++itr) { 27 printf("data == %d\n", *itr); 28 } 29 } 30

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

read_dataメソッドはスレッドセーフですか?

スレッドセーフでないなら一番簡潔な解決方法はClientAPIをthisで渡すのではなく、スレッド毎にClientAPIのインスタンスを生成してください。

投稿2017/06/23 06:05

編集2017/06/23 09:02
haru666

総合スコア1591

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こんにちは。

ところどころ、コピペ・ミスがあるようですので、単なるコピペ・ミスかもしれませんが、return_vectorの定義がありません。もし、これがresult_vectorのミスではなく、別途、各サブ・スレッドで共有されるような場所(グローバル変数かClientAPIクラスのメンバ変数)で定義されていたら、あり得る現象と思います。

投稿2017/06/20 09:51

編集2017/06/20 09:59
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kkkmokotan

2017/06/20 10:10

すいませんでした。return vectorではなくresult_vectorです。 ちなみに、 this->pool->enqueue([tmp, api] {}スコープの中で結果を出力させたところ、すでにこの時点で値がくずれていました。、
Chironian

2017/06/20 10:27

やはりそうでしたか。 シングル・スレッドで動作し、マルチ・スレッドでデータ破壊を起こす場合は、スレッド間で共有しているエリアのアクセスの排他制御を失敗しているケースが多いです。 スタック上の変数はポインタ等でアドレスを共有しない限りスレッド間で共有することは困難です。ラムダ式内のほとんどの変数はスタック上に確保されていますのでスレッド間の排他制御ミスによる破壊は考えにくいです。 スタック上に確保していない変数をread_data()関数がアクセスしている可能性があります。result_listは恐らく参照で受け取って内部でヒープから確保していると思いますが、他に何か共有できる変数をアクセスしていないでしょうか? 特にClientAPIクラスのメンバ変数をR/Wアクセスしていると危険です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問