C++相談室 part165
!extend:checked:vvvvv:1000:512
!extend:checked:vvvvv:1000:512
↑同じ内容を3行貼り付けること
次スレは>>980が立てること
無理なら細かく安価指定
※前スレ
C++相談室 part164
https://mevius.5ch.net/test/read.cgi/tech/1683600652/
VIPQ2_EXTDAT: checked:vvvvv:1000:512:: EXT was configured 例外安全と例外の種類には特に関係はないわけで、知らない例外だと例外安全の保証が困難になるなんてこともない。 >>284
例外の種類しか頭にないのか
任意の場所での例外発生に対応するなん現実的にできないということ >>269
そのあたりの難しさを考えると、例外廃止してoptionalに統一したほうがいいかもな。
少なくとも例外みたいに変なフローで飛んで来ないし。 ぶっちゃけ>>283がなに言ってるのかわからない
継続してそれが原因で?
いやいやw
突如落ちるより、保存できるデータは保存してもらう機会を与えることは出来るだろ
なんでお前は何事もなかったかのように作業を続ける前提でしか話を聞かないんだ?
オブジェクトの状態が変わっているかも?
変更前のデータと比較して変わっていたらユーザに確認すればいいだろ
例えば図形情報のうちTopの読み込みで例外が発生した場合に想定してないからとアプリ落として全情報ロストさせる気か?
Topは0で初期化させ読み込めなかったことをユーザに伝えて修正、もしくは再読み込みの機会を与えるだけの話だろ >>285
>例外の種類しか頭にないのか
>>283が仕様に明示されていない例外を話題にしているからだが。
>任意の場所での例外発生に対応するなん現実的にできないということ
これはどういう意味なんだろうな。
着目するのは自分が呼び出している処理から上がってくる例外に対して例外安全かどうかであって
それは基本的に局所的に判断できるもの。
下層の、例外が通過してきた処理が例外安全な実装になっているかどうかってのはそっちの責務。 > これはどういう意味なんだろうな。
そうそれ
tryブロックで囲った部分(つまり任意)の例外発生に対応するのが例外処理なのになにが出来ないというのか
想定している例外が発生して継続できると判断したなら続ければいいし
ダメならユーザに通知してもちょも安全な方法を選択させればいい
でもってそれは想定していない例外の発生でも同じ
ただ致命的でどうしようもないなら強制終了させるだけの話で、想定していない例外はなんでもかんでも強制終了じゃ例外処理使う意味が薄まってしまう >>287
ファイル保存するなとか言ってない
それぐらい終了処理のひとつだろ
ログファイルもシグナルトラップして必ずフラッシュさせるのが常套手段だろ
意味不明な例外が発生しました
データが破損してないかあなたが確認してください
動作無保証ですが処理継続しますか?yes/no
こんなUIだすやつセンスの欠片もない 私が20代の頃に見かけた論争が今も繰り返されてるのかわいい🩷 >>291
それを思いついたお前のセンスがないと言うことになるが…
俺は確認しろと言っただけだし確認には様々な方法がある >>291
まさか、何も言わずにいきなり落とす方が良いとか言うわけじゃあるまい。 >>280
実生活のあれと似てますよね。「引っ越すことになりました。新住所はXXです」と早めに
連絡したら、気の早い知人がそこに押しかけてきて「なんやまだ引越しとらんやんけ」となる
やはり引越し作業完了を待ってからの方がいいのか。ってちがうか >>282
>相変わらずずれてるな。 catch する == 原因を調査しない じゃないわけ
>249に賛同いただけていないということは、発生してもいない例外について予防的にtry { } catch () を入れようとしていることは
確定的に明らか
で、例外というブツは「例外なく」悪い知らせなので(∵仮に良い知らせを例外で寄越すライブラリがあったらそれ自体悪い知らせである
普通の人は悪い知らせが来る前に処置しようとする。すわなち例外が来ないように(可能な限り)修正する。
try { } catch ( ) でひっかけて原因調査兼確実な修正でざい、それが一番効率が良い方法論である、などと主張するのはおかしい人だけ…… >>284
例外安全というもののスコープに対して考察が足りていない
1.
例外安全なオブジェクト foo のデストラクトが他の例外によって引き起こされるケースでは
foo の安全な終了は(メモリかファイルステムか何かが物理的にぶち壊れてOSがパニックになったとかでない限り
ほぼほぼ保たれるから>>284のような言い方はできるっていやーできるが、
システム全体については>>283の通りであって全然安全ではない
2.
fooの中の例外処理が本当に完璧かはfooのコードに書かれている全てのtry { } catch () について
全ての例外発生条件についてテストか厳格めのコードレビューでも行わないことには安全性が担保されない。
(つまり例外安全にした実装したと主張するだけでは話がただちには簡単にはならない それはそうとして、予防的なtry{ } catch () の何が一番駄目かというと、設計上のトレードオフをわけわかんなくすることが確実な点
例外発生後の状況というのはたいてい>>283の通りのわけなので、何かを捨てて何かを取る
(例えばシステムは最悪落ちても構わないが、例外安全なオブジェクトfooでリソースAの整合性は死守する等)
のトレードオフが発生するがそういうのこそ慎重な設計と考慮が必要な事項であることは確定的にあきらか
プログラムの全階層にtry { } catch ()入れたら完璧などというアフォはやっぱtry { } catch () しないのが正しい >>298
自分が呼び出す関数が例外安全にできているかどうかと自分の処理が例外安全かどうかをごっちゃにしてるだろ。
しかも、呼び出す関数からドキュメント化されていない想定外の例外が発生するなら例外安全に作られていないだろうという
変な決めつけが混じってる。
例外安全なコードは例外の種類に依存しない。知ってる冷害に対しては安全だけど知らない例外が飛んできたら安全じゃない
なんてのはそもそも例外安全とは言わない。 >>300
お前さ、すべてのnoexcept関数呼び出しの例外テスト書いてんのか?
それが出来もしない理想論だって言ってんの >>301
自分でnoexcept指定した関数のことなら投げないことを確認するテストくらい書けよ当たり前だろ >お前さ、すべてのnoexcept関数呼び出しの例外テスト書いてんのか?
悪魔の証明をテストすんのか >>302
100%自分で書いてるコードなら未知の例外なんて起こらんだろ
話の筋理解してからレスつけろや三流 なんか予想外に低レなレスポンスを寄越した>>299……
さすがに>>283の後に>>284のような楽天的なことを言えるだけのことはあるということか……
例外安全は確かに目指すべき境地であり、例外安全なオブジェクトだけでコードを書けば
その関数は例外安全となる。try { } catch ()など一切不要、となるわけで一見実現が簡単に思える
が、例外安全なオブジェクトだけかをもれなく機械的に確認する方法は無い上に、
中断したら別物になる(処理の順序が命)というアルゴリズムというものの本質的特性により、
>>183 のような try { } catch () が必要なケースは隙あらば混ざり込んでくるから(※1)
>>284が空想するようなシステム全体の例外安全化などは現実には不可能。
せいぜいある程度の規模のオブジェクトであれば、十分テストすれば
(自分が呼び出す関数が例外安全にできているかどうかと自分の処理が例外安全かどうかを慎重に確認せねばならない)
ほぼほぼの信頼度で実現できるというぐらい。 (※1) >>183 の関数そのものは、例外安全なスレッドオブジェクトでも使ったらtry { } catch () 無しの例外安全な関数うに書き直すことはできうる あと寝てて思ったがプロセスが死んでもサービスが継続したらお客様には迷惑を掛けずに済むので
(直接そういうのをやってちるわけではないので強くは言わんが
ウォッチドッグタイマー的な死活監視で異常あらばプロセス再起動とかマシンを切り替えるとか方法はいくつもあって、
十分テストされたプログラムならクラッシュ頻度をポアソン分布とみなして信頼度も出せる
やっぱ「お客様の前で落ちたら恥ずかしいから」というつまらないプライドを基本的動機とする
try {
....
} catch (std::exception& e) {
log_e("std::exceptionがスローされました");
};
みたいなコードをリリースコードに含めましょうという>>282の調査のスタンスは全く正当化されない
100日に一回しか再現しないバグの修正を3日でやれと言われて手元にあるのがメモリダンプの代わりに上の23文字のログメッセージだけだったりしたら
>>282は自○が真剣に考慮すべき選択肢に…… > なんか予想外に低レなレスポンスを寄越した>>299……
299はお前自身じゃないのか、と俺は思う >例外安全は確かに目指すべき境地であり、例外安全なオブジェクトだけでコードを書けば
>その関数は例外安全となる。try { } catch ()など一切不要、となるわけで一見実現が簡単に思える
例外安全だからといってcatchが不要になるわけないだろ。
根本的なところで勘違いしてるから頓珍漢が主張を続けてるわけだな。 例外安全には基本保証・強い保証・no-fail保証がある
例外がスローされない関数を作ればno-fail保証がある
基本保証や強い保証は例外発生後も不整合が発生しないもの
たとえば例外が発生した関数をもう一度呼び出すと「すでに実行中です」とエラーを返すようなものは例外安全ではない(おそらく実行中フラグ変数が立ったままになっている) 10行のデータをファイルに出力するとき、例外が発生して5行だけデータが出力されてしまうのは強い保証があるとはいえない
例外が発生した際にデータを書き込む前のファイル状態に戻れば強い保証がある(例外安全である)といえる 誤解のないように念のため補足。
この場合の「強い」という用語は性質の分類であって強いことがより良いというわけではないという話をしてる。(んだよね?)
例外を出さずに済むならそれに越したことはないよ。
でも、ひとつの部品の中では問題を解決できないことがあるからこそ例外を用いて他の部品と連携しての解決を試みるわけ。
連携するには保証の強力さよりも保証範囲の明瞭さ (明瞭でもカバーしようがない設計はあかんが) が大事で、プログラム全体で整合性が保たれていれば例外安全と言える。
仕様が不明瞭なライブラリもあるのが現実だってのはそりゃそうだけど、出来が悪い部品とつじつま合わせをしきらないってのは例外のせいでも C++ のせいでもない。 std::initializer_listについて質問です
下の例ですがコンストラクタの引数に配列リテラルを指定した場合、リストがコピーされてしまいますよね?
これは無駄なので回避したいのですが良い方法はありますか?
https://cpprefjp.github.io/reference/initializer_list/initializer_list.html リテラルのコピーを気にするならconstexprじゃねーの?
ほんとにコンパイル時に定数になるかは知らんけど >>313
C++ に配列リテラルはない。
その書き方で出てくる波括弧はリスト初期化の構文の一部で、
波括弧の部分単体は配列リテラルではない。
実行時にオブジェクトの構築を避けるならコンパイル時に構築することになるが
それはそれで色々と制約があるんでほんまにそれが必要なんか?
というのはよく考えないといけない。
あえてやるならこんな感じかな……。
https://wandbox.org/permlink/HStrLq8ddyC3tby2 とあるtemplateの関数を実装しているのですが、
const指定の振る舞いがよくわからなくなったので
質問させてください。
以下の(だいぶ簡略化した)コードで、
f_without_const<const int*>(const int* a)
はコンパイルが通るのですが
f_with_const<int*>(const int* a)
がコンパイルが通らないのは何故でしょうか。
https://wandbox.org/permlink/OIgKM2DTqvpGduRV >>316
なるほど
ここまでやるメリットはなさそうなので大人しくデフォルトの書き方にしておきます >>317
templateは型が違うと全くの別物として処理するからだと思う >>317
template <class T> void f_with_const (const T t);
これに対応させるなら f_with_const<int*>(int *const a) const T t に対して const int* a が来たら
字句の順序としては T に int* が対応してるように見えちゃうもんな……。 317です、返信遅くなってすみません
確かに言われてみればconstが修飾してるのはint*なので、意味的にint *constが正しいですね…
ありがとうございました 先月東京で標準化委員会の会議あったらしいけどなんか情報ないの? python みたいに何でも格納できる辞書型ってC++には無いよね? >>326
要素を std::any にすればだいたいどんな型の値でも入れられる。
いろんな型を入れたところで使うときには元の型として取り出さないといけないから
処理は煩雑になってあまり良いことはないけど。 cpprefjpが間違ってるだけ?
それともずっと規格から欠落してたけど誰も気付いてなかったパターン? elifを逆から読んだらfile
ラリーはこれを嫌ってPerlではelsifにした(適当 シェルが変だからな
case ~ esac
if ~ fi 質問なのですが
Q1. std::fstreamでファイルを開くときのフラグの指定の仕方は次のどれが正義?
std::fstream ofs("foo.txt", std::ios::out | std::ios::binary); // (1)
std::fstream ofs("foo.txt", std::basic_ios::out | std::basic_ios::binary); // (2)
std::fstream ofs("foo.txt", std::fstream::out | std::fstream::binary); // (3) fstreamなんだったらfstreamのメンバで書くのがいいんじゃない (1)は#include <ios>が要るし、
(2)は「basic_」の6文字×フラグの数 だけ長いし、
(3)も同様でありなおかつ>>337に従ったとき
use binary = std::fstream::binary;
use ibinary = std::ifstream::binary;
use obinary = std::ofstream::binary;
となってしまい、
どれもこれもコード量最小化原則的にビミョーなことに……
ていうかなんで同じことをするのに複数の書き方があるのかっていうか、
Perlじゃあるまいし…… C++の悪評の4割くらいはiostreamのせいだからな ここでCmakeとNinjaについて聞くのダメ?
どーも関係がよくわからなくて? >>342
そういう雑多な話題のちょうどよいスレは見当たらんし、単発で終わる質問程度なら許容されると思うが……。
質問の内容が漠然としているなら丁寧な回答は得られないと思う。
「よくわからない」という状況になるときってのは大抵の場合に関連する前提知識が足りてないので
質問が連鎖的に発生してダラダラ続いたりするから。 >>336
第四の選択肢
std::fstream ofs("foo.txt", ofs.out | ofs.binary); >>344
ofsのスコープの隙間を突きなおかつ静的メンバをドット演算子で参照する等
テクニカルですばらっし 静的解析で文句言われる可能性あるからやめときな
頻発するならスニペット作ればいいだけ
そういう表面的なことにこだわる奴は三流 lldb v14.0.0 で正しくプロセスを実行できません
apt insrall でインストールしたもので, 環境はwsl 1 です
具体的には下のサイトのIssue Encountered:と全く同じ症状です
https://stackoverflow.com/questions/78275920/troubleshoot-lldb-on-ubuntu-wsl
改めて書きますと Hello World 表示だけのソースを clang でコンパイルし,
lldb で読み込み run させると
Process 20784 launched: '/home/Hustler/c++/move/move' (x86_64)
と表示されたまま応答がなくなり 放置すると(サイトでは強制終了させてるようですが)
Process 20784 exited with status = -1 (0xffffffff) lost connection
となってコマンド入力待ち状態となります
ちなみにプログラムはそのまま実行して正しく動作しますし gdb でも何の問題もありません
これに関して何か情報をお持ちの方いますか? 今やってみたのですが
lldb-14をuninstall(remove)し lldb-15をインストールしてみましたが
状況は改善しませんでした WSL1 は (ある程度) Linux 互換のシステムコールを windows 内に実装することで実現していて Linux カーネルそのものではないので色々と不足がある。
(そのかわり Windows と親和性がある部分もある。)
WSL1 で用意してない Linux の機能に依存したアプリケーションは動かない。
まともな互換性が必要ならWSL2 を使いなさいという話なので手間をかけて WSL1 を積極的にはサポートしないと思う。 >>352
wsl2 ではlldbは問題なく動いてるんですか?
古いCPUなのでwsl2がインスコできないもんで
上のサイトはwslのバージョンは書いてなかったようですし WSLはlldbが使うシステムコールが足りてないって昔から言われていたかと
ターゲット機を別にするとかWSL2にするとかじゃね? >>354
>WSLはlldbが使うシステムコールが足りてないって昔から言われていたかと
なるほどTHXです
clang使ってなかったので全然わかりませんでした
動かないlldbもさんざんggったんだけど system call未実装にはたどり着けませんでした
ようやくすっきりしました ざっとググってみた感じたと wsl1 では procfs が提供する情報が少ないのが lldb が動かない直接の原因みたいな数年前の情報は見つかる。
内部構造がまるで違うはずなのに表面的なインターフェースは互換にするなんてのは無理のある話なので互換性が「ある程度」にとどまるのは仕方ない。 んー
clangちょっと調べたかったんで
Visual Studioにclangインスコして調べますわ
できるならwslでやるのが手っ取り早いんですが
Q9550とQ9550sしか持ってないもんで
以来CPUの爆値上がりと最近の円の爆下がりで新しく組めてないんですわ
ダイサイズ変わらないのにCPU 3万ー> 10万とか購買意欲が萎える >>355
github のwslのissueを漁れば出て来るかと。
結論がWSL2使えだったかと 自己レスです
その後 Visual Studioのインストールオプションでclangを選択し
正しく動作することは確認したのですが...
今や誰でもロハで使えるインテルコンパイラがとっくの昔にllvm化されてたんですね
clangに拘りがなければ x86/x64のwin/linux/wsl は素直にopenAPI使っとくのが幸せかも.
ちなみにwsl 1にlinux版をインストールしましたが
コンパイラicxもデバッガgdb-opwnapiも何の問題もなく動いてます(今のところは)
なので
Visual Studio はインストールオプションのclang は外してもとに戻し
wsl は
>apt remove clang clang-15
>apt remove lldb lldb-15
しときました