アンワインド セマンティクス って何?

Visual Studio でコマンドプロンプトのCLを使って、最初に受ける洗礼。

C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.10.25017\include\xlocale(314):
warning C4530: C++ 例外処理を使っていますが、アンワインド セマンティクスは有効にはなりません。/EHsc を指定してください。

意味が分からない。

ヤフー知恵袋とかで調べてみたが、/EHscつければ解決とかワーニングとおなじこと言ってドヤ顔してるの以外、何言ってるのかぜんぜん分からんし。あんたら最高、天才。

Q:「アンワインドセマンティックス」とはどういう意味ですか?教えてください。→A:メッセージ読めないの?バカなの?  “/EHsc”付ければおk!
http://qa.itmedia.co.jp/qa4559129.html
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q10119567590
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1056479490

日本語が理解できる大半の人はcl に /EHscを追加すればいいと分かるし、実際それが正解だけど、じゃあC++例外? アンワインド セマンティックス?  が有効? 何それ、はぁ?? てなるわ。えぴすてーめー様も回答が超小出しでセマンティクスが全然かみ合ってないし。

セマンティクスて何、て調べるとどうもプログラムの上では「中身」とか「内容」とか「意味」ってことらしい。

http://www.itmedia.co.jp/enterprise/0108/20/01082088.html

じゃあ、「アンワインド セマンティクス(unwind semantics)」って何やねん? で調べても最初に出てきたエラーが解決しませんとかいうしょうもない質問にlongjmpするばかりで、肝心なところが出てこない。

※実際のところMSDNで/EHscのオプションの説明を見ると例外処理とデストラクタが呼ばれる呼ばれないの問題であることはすぐに分かるので、最初のヤフー知恵袋の回答はいい線行ってるが、この言い回しでは質問者には分からないでしょうね。ここでは「アンワインド セマンティクス」というキーワード自体が意味不明であることにフォーカスする。

次のコード、最新のIoTデバイス「コタツみかん取得装置デバイス」に組み込まれる予定のMikanオブジェクトはコンストラクタで「自動的にミカンを持ってくる。」、デストラクタで「自動的にミカンを返却する。」が実装されている。現時点でMikanオブジェクトはPeelAndEat(剥いて食す)メソッドを実装していないので持ってきたMikanは必ず返さなければならない。Mikanの返却を忘れた場合、それはリソースリークを意味する。

#include 

int main(void)
{
	class Mikan {
	public:
		Mikan() { puts("Bring Mikan"); }
		~Mikan() { puts("Takeback Mikan"); }
	};

	puts("Start.");

	try {
		Mikan AmaiMikan;	// Mikanの自動インスタンスAmaiMikanを生成
		throw NULL;		// ぬるぽ
	}
	catch(...) {
		puts("Catch.");		// ガッ
	}

	puts("End.");
	return 0;
}

CLのオプション/EHsがあるときとないときの違いを見てみる。実行環境は最新のVisual Studio 2017。

▼あるとき

C:\>cl /EHs sem.cpp && sem
Microsoft(R) C/C++ Optimizing Compiler Version 19.10.25019 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

sem.cpp
Microsoft (R) Incremental Linker Version 14.10.25019.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:sem.exe
sem.obj
Start.
Bring Mikan	←みかん持ってくる。
Takeback Mikan	←みかん返す。
Catch.		←例外処理中。
End.		←終了。

try文中でMikanオブジェクトのインスタンスAmaiMikanが自動的に生成され、コンストラクタが呼ばれ、その直後に例外をthrowして、tryスコープから外れる、catchのブロックに入る前にAmaiMikanのデストラクタが呼ばれている。当たり前といえば当たり前の動作。

▼ないとき

C:\>cl sem.cpp && sem
Microsoft(R) C/C++ Optimizing Compiler Version 19.10.25019 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

sem.cpp
sem.cpp(14): warning C4530: C++ 例外処理を使っていますが、アンワインド セマンティクスは有効にはなりません。/EHsc を指定 してください。
Microsoft (R) Incremental Linker Version 14.10.25019.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:sem.exe
sem.obj
Start.
Bring Mikan	←みかん持ってくる。
Catch.		←例外処理中。
End.		←終了、みかん返却されていない。

例のワーニングC4530が出ている。今度はtryブロックから出ても、プログラム本体が終了してもAmaiMikanのデストラクタは呼ばれずに終了している。これは期待するtry ~ catchの動作ではない。

この動作では自動変数のAmaiMikan自体はスコープから外れるときにスタックメモリ(スタックフレーム)から削除(フレームのアンワインド)されるが、その処理中にはデストラクタが呼ばれず、クリーンアップを行う処理(=アンワインド セマンティクス)がされない。

最初に書いたとおりセマンティックス=内容てことだったから、「アンワインド セマンティクス」を雑に訳すと「内容を巻き戻す」。さっきのコードの動作が分かると、分かった気がする。オプション/EHがException Handlingの略だってことも分かる。

もうちょっと違う言い方(余計に分かりにくく)すると、

・ビデオテープを再生している途中で、あるところに戻りたいので巻き戻しをする。

  • 巻き戻す内容を見ながら戻りたいところに戻る。
    →セマンティクス(内容的に必要な処理(例えば消去)をしながら)に、アンワインド(巻き戻す)。
    →/EHsオプション有り、普通のC++ try~catch例外処理。
    .
  • 再生時間表示だけを見て、戻りたいところに戻る。
    →セマンティクスな処理をせずに(中身に干渉せずに)、アンワインド。(巻き戻すだけ)
    →/EHsオプション無し、MS独自仕様な例外処理の動作。
    .

CLが/EHオプション無しでこのような動作になるのはおそらく歴史的経緯でCLコマンドの後方互換性(MS-C/C++7.0やVC++1.x(たぶん)とか初期のMSC処理系はC++例外処理が実装されていなかった)によるものだと考えられるので、try~catchでまともな動作をさせたければ単純に言われたとおり/EHscを付けてあげるのが正解。

久しぶりにプログラムの細かい内容になった気がする。こんなことはプログラマでも知らない人がわりといるのに、自分のような非プログラマが知る必要はまず無い。

スタックフレームの理解とかは気が向いたら追記予定。

コメントを残す