C言語なら俺に聞け 142 [無断転載禁止]©2ch.net
■ このスレッドは過去ログ倉庫に格納されています
確かに馬鹿な奴もいるけどレベルの高い奴もいる。コーダーに限った話じゃないだろ。
日本に馬鹿が多いんだよ。たぶん。 >>296
俺より年収1桁少ないやつにだけは言われたくねえぜ
なに、2桁? そりゃ失礼したw 妻子持ちがどのくら金いるか
童貞にはわからんようだな >>298
奴隷的労働しか選択肢が無いのに妻子持ち
妻子が哀れすぎる >>305
奴隷? 俺は領主の立場だ
おまえと一緒にするな無礼な >>306
僕のお父さんは奴隷のリーダーですってか? 馬鹿な奴隷に指示、管理する者の気苦労が分からんのか >>301
妻はまだ自分の食いぶちの一部でも稼がせばいいけど子の方はマジで金かかる
国は学資保険なんてものがあることをちょっと恥じるべき 金持ちしか子供作らせないのは国策
やつらに恥などない
怒れ >>312
俺は金持ちじゃねえ
単年度で8桁いっても次年以後で気を抜けばボコボコだ
一生遊んで暮らせる金があるやつにしか子供を作らせないなんて国策はねえ
童貞がイソップの葡萄こいてろ、こちとら稼いでみせると必死こいてんだ ポッキリと折れて周囲に生暖かい目で見られるところまで見えた >>299
3桁って、10進数だと999円が限界だぞ 昔"c言語をダイエットさせる本"みたいなタイトルの本読んだと思うんだが分かるやついる?
見つからなくて探してる for(;~scanf("%d",&a);)とかwhile(~scanf("%d", &a))とかで~がないだけで永遠に入力ループするんだけど
~ってなにを宣言してるんだ教えてくれ 本来なら 変数a に格納されるまでループしたい意図だろうけど・・・・・
scanf の戻り値は 代入操作できた変数の数で
0 だと入力のフォーマットに合致しなかったわけなんだが (ここまでは素直)
一旦 その状態になると、次に正しく入力しても拾ってくれない scanf 独特の挙動があって
正しく入力しようが 0 のままというkuso
件の場合
最初の入力で数値ではない o を与えると (%d で受けれないので失敗)
次のループの入力で 1 を与えても やはり変数に格納ざれずに失敗したまま
これがあるので scanf は使うな、と良く言われてる所以 一行読み込みで同じ処理を数値なくなるまでしたいんだけどどう読み込んだ方がいい? fgets で行単位で読み込み
その行バッファに対して sscanf で変数に拾い上げするなり、11文字ずずつ字句解析するなり
char buf[512];
int a;
while (fgets(buf, 512, stdin)) {
/* 1行読んだよ */
if (sscanf(buf, "%d", &a) != 1) {
/* 数値じゃないのが来たのは無視する */
continue;
}
/* a に値が格納されたよ */
:
} 日本語でおけ
× 11文字ずずつ字句解析するなり
○ 1文字づつ字句解析するなり >>327
strtolとかstrspn?系つかったほうがよくね? >>325
まじかよ..
scanf呼び出して戻ってきたあとも何かしらのscanf内部変数が残ってるってこと?
だとしたらクソ過ぎるだろ >>330
標準入力を勝手に読み捨てないってこと
数値以外が来たら"何もせずに"失敗で終わるから
ループするとまた失敗以前の場所からそれを繰り返すだけ forの継続条件がどう動いてるのかわからないな読み込めた時はループして読み込めなかったときはループ抜けるってのがどう判定されてるのか見えないな >>333
scanf("%d",&a);
で、数値が来れば取り込みに成功した個数、つまり1を返し、失敗なら0を返す
それを~でビットNOT、つまり各ビットを反転させるので
成功なら0x00000001を反転で0xFFFFFFFE、失敗なら0x00000000を反転で0xFFFFFFFF
ようするにどうやってもループを抜けないので、結論としては「そもそもループ条件として間違ってる」
>>324の言う通り~は不要 もっとシンプルに使える入力関数を
誰かが作ってくれれば良いのに >>335
簡単なので多分もう世界中に山ほどあると思うが、標準化されてないだけだろうな。 while((a=Console.ReadLine())!=null)こうゆうので入力がなかったら終了するって簡単にできればC言語も楽なんだけどな int *get_int(int *dst, jmp_buf err)
{
if (scanf("%d", dst) != 1)
{
if (err) longjmp(err, 1);
else return NULL;
}
return dst;
}
こんなしょーもないのでいいのに標準化委員会は斜め上なことばかり・・・ >>334
でもscanfの前に~あるだけで入力なくっても無限ループしないで抜けるのはNOTと戻り値がNOTでtureだから抜けるの? チルダ付けたのは失敗した時に-1が返されると思ったからかな?
てか、チルダ付けた場合はそれ以外で0にならんよな。
まあでもこれも整数値の内部表現の違う特殊な環境だったりしたらダメかも知れないが。 普通にビット処理だと使うよね
ビット処理なんかしないって? ごめんウソ書いたわ
一つも変換されないで入力エラーになったらscanf()は0ではなくEOFを返すらしい
>>339
よって多くの環境ではEOF==-1(0xFFFFFFFF)だからその反転で0になってループ抜けるということだね >>343
入力ストリームが閉じてて変換できなかったら EOF
入力ストリームは開いてるけど変換できなかったら 0
でないのけ? >>345
どうやらそのようだな。Linuxのmanで見てみたらそんな風に書いてあった。
とすると入力が閉じないで変換失敗した場合は0が返されて無限ループになるな。 Win32環境なのですが
_beginthread関数で、thread1, thread2を回し
グローバル変数g_nをthread1の中で変更しても
thread2から正しい値が参照できません。参照できないというよりthread2が機能しなくなるように見えます。変数表示がカットされる。
VisualC++でプログラムしてるのですがデバッグモードだと普通に動いて
リリースモードだと動かなくなります。グローバル変数にvolatileをつけてみてもダメでした。
何が原因でしょうか? 具体的なコードもなく原因を聞かれても、どうしようもないと思うぞ
VCの拡張機能で相応の機能が追加されてたような気もするが
本来volatileにスレッド間での排他やメモリバリアの機能はないからな >>347
デバッガ側で例外をキャッチして、呼び出し履歴を調べると何かわかるかもしれない。おそらくゼロ除算かアクセス違反かスタックオーバーフロー。 >>348-349
thread2の中身を以下みたいにtry〜catchで囲むと何故か直りました…
でもcatchの中は実行されてないです… 少しcatchの中身を書き足すとまたダメ…
どういうことだろう…
void thread2(void*)
{
try{
…
} catch (...) {
…
}
} >>352
>呼び出し規約が間違い
これはどういう事ですか?
宜しければご教示をm(__)m https://msdn.microsoft.com/ja-jp/library/kdzttdcb.aspx
_beginthreadexの場合は、__stdcallを関数名の前につける。_beginthreadの場合は、__cdeclを。
__cdeclはデフォルトでは省略可能だから、間違ってはいない。
ということは、ポインターかなんかでスタック破壊している可能性が高い。 >>356
もう少し深く調べてみます!ありがとうございます! >>356
たぶん原因が分かりました。
現在は標準関数をやめてWINAPIのCreateThreadを使ってますが標準関数と原因は同じです。
CreateThreadでThread1,Thread2を作成して監視してるとあるタイミングでThread2が消失してたのですが
どうやらThread1で変更があった他のグローバル変数の値がThread2で上手く読めずに終了判定されて消えてたようです。
ようするに他のグローバル変数の書き換えが原因でした。
ロック処理をしたりしたのですが上手く行かずグローバル変数すべてにvolatileをつけると上手く動いてるようです。
でもこの回避作で良いんでしょうか?CriticalSectionを使ったりして処理してもうまく他スレッドでグローバル変数が
参照出来なかったのでvolatileをつけてみたら完璧に動作するようにはなったんですが…… 排他制御の問題ではなく
最適化の作業で、変数を不変値と判断し、変数参照を追い出した翻訳をしたパターン
int a; // グローバル変数
void foo() { a = 1; while (a) { /* */ } }
a は文意から不変の定数として扱えるので
while (1) { /* */ }
に翻訳しちゃえるわけさ >>359
その変数達の最適化を無効にしたということですね。
ということはこの回避方法で大丈夫だということですか? volatile つけるのは1つの手ではあるが 100% 回避してくれるかは、コンパイラ次第
スレッドで共有するフラグ関係はOS側が用意してる機構を使うほうが良いんだけどねー >>361
一旦コンパイルして普通に動作してるなら大丈夫ですか?
他の環境でいきなり動かなくなるとかもありますか? 何の変数を使ってるか知らんが、排他取ってねーんだから書き換え途中の変数を読み取ってバグることもあるだろ
最近のVCはvolatileだけでマルチプロセッサ対応のメモリバリアになるらしいから、古いVCでビルドしてもアウトだな
まあ滅多に起らないからローカルでそれっぽく動けばいいのなら、十分じゃねーの >>358
いや、359ではなくて、363の言うとおり、
> ロック処理をしたりしたのですが上手く行かずグローバル変数すべてにvolatileをつけると上手く動いてるようです。
これが問題だと思うぞ。つか、ロックしろよ。
volatileの意味分かってるか?
それ多分他スレッドから書き換えられたときに自スレッドのその値が更新されておらず、バグるのだと思うぞ。
ただしこの場合は、
> 最近のVCはvolatileだけでマルチプロセッサ対応のメモリバリアになるらしい (>>363) ←コマ?
が正しいのならvolatileでも確かに治りそうな気はするが。で、これってマジなん?
つかね、マルチスレッドでグローバル変数を使いまくること自体がだね、、、 >>363
調べてみたんだが、これか?
> Microsoft 固有の仕様 → /volatile:ms の項目
> ・volatile オブジェクトへの書き込み (volatile 書き込み) は、解放セマンティクスを持っています。
> つまり、命令シーケンスで volatile オブジェクトへの書き込み前に発生するグローバル オブジェクトまたは静的オブジェクトへの参照は、
> コンパイルされたバイナリでの volatile 書き込みの前に発生します。
> ・volatile オブジェクトの読み取り (volatile 読み取り) は、取得セマンティクスを持っています。
> つまり、命令シーケンスで volatile メモリの読み取り後に発生するグローバル オブジェクトまたは静的オブジェクトへの参照は、
> コンパイルされたバイナリでの volatile 読み取りの後に発生します。
https://msdn.microsoft.com/ja-jp/library/12a04hfd.aspx
これならロックではなくフェンスだね。volatileでは直らないはず。 >>365
自分も見かけただけでちゃんと調べたわけじゃないけど、それだね
フェンス+ロックが必要ってのは当然として、最近のVCならフェンスのほうが保証してくれてるってだけ >>361-365
CriticalSectionつかってグローバル変数の書き込み時にはロックをするのも試してみたんですが
やっぱりthread2が途中で死んで(内部のループで終了判定になってしまって)、ダメだったんですよね。
それがグローバルにvolatileをつけると普通に動作するようになってるんです…… こういう事ですか?
CriticalSectionによるロックもやる必要がある。理由はロックしてない時固有の問題もあるから。
今回の不具合はコンパイラの最適化が原因だったのでvolatileで回避できただけ。
ロック処理もvolatileも両方やる必要がある。ということですか? 書き込み時だけロックして 読み込み側のほうはロックせずに読み込んでる
片手落ちのように受けとれる文章だけど・・・ 排他制御をちゃんとやってたうえでの話? volatileにしてロックして読み書きするのが普通では? >>369-370
volatileにして読み書きロックして厳密にやります! >>368
× > 今回の不具合はコンパイラの最適化が原因だったのでvolatileで回避できただけ。
○ コンパイラの不具合ではなく、君のコードの問題で、
volatileで動いているように見えるのはバグに当たる確率が低くなっただけで、直ってはいない。
ただ、366の通り、全部ロック+フェンスすれば直りそうな気はする。
つか、そもそもフェンスが大量に要るような使い方でマルチスレッドするのが問題なんだが。 posixだとロックAPIにメモリ同期の効果があるから、普通はvolatileいらんけどな
CriticalSectionも共有リソースへのアクセス制御用の関数なんだから、同じはずだと思うけども >>372
コードの不具合って意味だろ?
やっぱり最適化が問題だったんじゃないか? >>374
> どうやらThread1で変更があった他のグローバル変数の値がThread2で上手く読めずに終了判定されて消えてたようです。(>>358)
この場合はvolatileをつけないと話にならない。(ただし本来の使い方ではない)
コンパイラのバグではなく、多分デバッグビルド時には毎回読み出しだっただけ。(最適化なし、なおフェンスもなし)
データ同期する気がなければフェンスは本来は要らない。
ロックはしないと書きかけの値を掴んだりしてバグる。
ここら辺分かってなくてグローバルで同期ってのはマルチスレッド初心者なのだろうけど、
バグったらsync入れまくってデバッグはセオリーではあるし、まあがんばれ、と。
ただ、おそらく同期の仕方を根本的に間違ってるから、知ってる人に見てもらったほうがいいとは思うが、
コード内のグローバルは常に「最新」を期待しているのであれば、ロック+volatile+フェンスで動くはずでもある。 ロック中の読み出しが最適化で消えるなら、それはロックとコンパイラが腐ってる >>372
> ○ コンパイラの不具合ではなく
誰もコンパイラの不具合なんて言ってない
偉そうに頓珍漢な講釈たれる前に日本語勉強し直してこい >>373
メモリー同期と最適化は別の話
Posix は知らんけど CreateSection にはロック対象を知るすべはない はあ、そうですか
共有リソースの排他アクセスのためのAPIなのに、ロック対象がわからないからロック無視して最適化しますと
それが真実ならWinAPIとVCが腐ってるんじゃないですか メモリバリアを跨いでオブジェクトへのアクセス命令を最適化するとか
そんな頓珍漢なことを言う腐った奴がいるとは思わなかったわ
volatileを何だと思ってんだか CreateSection の使い方ぐらい調べてから書けばいいのに...
まあ他人事だしどうでもいいけど w CriticalSectionの話のつもりだったんだけど、CreateSectionに変わったの?
それならごめんだわ、>>378で唐突に出てきて誤字だとばかり
さすがにそんなアホな話題転換があるとは思わなかった >>385
ああすまん、予測変換で間違えてたわ
で、CriticalSection について調べたのかな? >The following synchronization functions use the appropriate barriers to ensure memory ordering:
>Functions that enter or leave critical sections
>Functions that signal synchronization objects
>Wait functions
>Interlocked functions
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686355(v=vs.85).aspx
調べたけどCriticalSectionだけで十分そうだよ
Internallockedとかのほうが手軽そうだけどね https://teratail.com/questions/39986
これの投稿 2016/07/04 10:48の例にあるように
最適化で変数の効果が消えてしまう場合でも
volatileじゃなく変数書き込みや参照の部分に
CriticalSectionでロックしておけば最適化で消える事はないということ? Cのコンパイラはクリティカルセクションなんて知らない。単なる構造体かなんかのtypedefとして実直にコンパイルするだけ。
スレッド関連の関数についても単に関数の一種として扱うだけ。
従ってスレッドやクリティカルセクションを扱っているかどうかが最適化の結果に影響することはない。
一方volatile指定はコンパイラが認識するキーワードで最適化に影響する。 ということは今回の事例だと排他制御しても不具合は解消できなかったという事かな?
volatile付けて最適化を無効にすることが正しい解決策だったということになる? >>387
だからそれはメモリーバリアの話で最適化の話とは別だよ
繰り返しになるけど CriticalSection は排他制御するリソースを知ることはできないしコンパイラも CriticalSection のことを知らない >>390
どう言うことをやりたいのかよく見てないけど排他制御と最適化の話は別だから必要なら両方やらないとダメ >>389
それ、スレッドまわりが規格化されてなかった C99 までの話だよね? ■ このスレッドは過去ログ倉庫に格納されています