syghの新フラグメント置き場

プログラミングTipsやコード断片の保管場所です。お絵描きもときどき載せます。

WindowsのOutputDebugString()関数とUnicode

WindowsOutputDebugStringW()関数とOutputDebugStringA()関数は、デバッグコンソールに文字列を出力します。

Visual Studioデバッグ実行すると、「出力ウィンドウ」に文字列が表示されます。
ただしAndroidのLogcatや、MacXcodeNSLogと違って、末尾に改行は自動付与されません。

ここで、

OutputDebugStringW converts the specified string based on the current system locale information and passes it to OutputDebugStringA to be displayed. As a result, some Unicode characters may not be displayed correctly.

と説明されているんですが、Visual Studio 2013までは確かに以下のようなコードは文字化け*1して日本語cR???となってしまうものの、Visual Studio 2015以降は正しく表示できています。

#include <Windows.h>

int main() {
    ::OutputDebugStringW(L"日本語©®™♡♥\n");
}

以下の説明から推察するに、VS2015ではWindows 10で追加されたAPIWaitForDebugEventEx()」をコールすることで、Unicode出力を実現しているようです。確かWindows 7/8.x上では、VS2015であってもOutputDebugStringW()Unicode固有文字を出力することはできていなかったように思います。

Important
In the past, the operating system did not output Unicode strings via OutputDebugStringW and instead only output ASCII strings. To force OutputDebugStringW to correctly output Unicode strings, debuggers are required to call WaitForDebugEventEx to opt into the new behavior. On calling WaitForDebugEventEx, the operating system will know that the debugger supports Unicode and is specifically opting into receiving Unicode strings.

ATLTRACE

ATL/MFCアプリやWinRTアプリでは、デバッグビルド時のみ有効になるATLTRACE()マクロ (atltrace.h) を使ってOutputDebugString()を間接的に利用することが多いですね。このマクロは第1引数に書式文字列を受け取るので便利です。MFCTRACE()マクロ (afx.h) は、ATLTRACE()と同じです*2

ただしVS2013 (ATL 12.0) 以降のATLTRACE()では、

hoge.cpp(123) : atlTraceGeneral - 出力メッセージ

というような感じで、ファイルパスと行番号と診断レベルが出力メッセージ先頭に付加されるようになりました。
Visual Studio IDEの出力ウィンドウでは、「FilePath(LineNumber):」の形で表示されたメッセージをダブルクリックすると、該当するソース行にジャンプできる機能が昔からあり、そのため __FILE____LINE__ を使って書式化されたメッセージを出力することがよくあったんですが、特にユーザーコードで工夫するまでもなく自動的にこの機能が利用できる形になりました。
ただ、常時出力されてしまうため、情報量が増えることでノイズも増え、メッセージ本体が埋もれてしまってうっとうしいと感じることもあります。

System.Diagnostics.Debug

.NETのDebug.WriteLine()メソッドやDebug.Print()メソッドは、VS2012/VS2013でもUnicode固有文字を出力できました。

System.Diagnostics.Debug.WriteLine("日本語©®™♡♥");

System.Diagnostics.Debugも内部的にOutputDebugStringW()を使っていると思っていたんですが、以下の解説によると、マネージコードに関しては別のデバッグエンジンが使われるため、OutputDebugStringW()の問題を回避できるようです。

Note
Visual Studio includes its own debugging environment and debugging engine, which together are called the Visual Studio debugger. For information on debugging in Visual Studio, see Debugging in Visual Studio. For debugging managed code, such as C#, using the Visual Studio debugger is often the easiest way to get started.

記憶が定かではないのですが、.NETのほうは確かWindows 10だけでなく、Windows 7/8.xでもUnicode固有文字を出力できていたような気がします。

*1:厳密に言うと「文字化け」というよりは、Unicode文字からCP932 (Shift_JIS) 文字へのマッピングが不可能であるために、代替文字に自動変換されています。

*2:昔はATLとMFCは別々に実装・メンテナンスされていたのですが、VC7で統合されていて、MFCアプリからはATLの機能がすべて使えるようになっています。

絶対値関数absとオーバーフロー

C/C++において、符号付き整数の絶対値を求める関数abs(), labs(), llabs()および整数型のstd::abs()関数オーバーロードには罠があり、「整数オーバーフロー」が考慮されていません。
これは、JavaC#のような近代的な言語と違って、C/C++の整数内部表現が2の補数系であるとは限らない、ということも関係しています。

C言語では、2の補数系において、整数型を受け取り整数型を返す絶対値関数にINT_MINLONG_MINなどが渡されたときには、各絶対値がそれぞれの型intlongなどで表現不可能なため、未定義動作 (undefined behavior) を引き起こします。

同様にC++では、2の補数系において、整数型を受け取り整数型を返すstd::abs()関数オーバーロードINT_MINLONG_MINなどが渡されたときには、未定義動作 (undefined behavior) を引き起こします。
なお、C++03以前では、<cmath>には浮動小数点数型を受け取るstd::abs()オーバーロードのみが存在しますが、C++11以降では整数型を受け取るオーバーロードも存在します。
また、C++14以前では、<cstdlib>には整数型を受け取るstd::abs()オーバーロードのみが存在しますが、C++17以降では浮動小数点数型を受け取るオーバーロードも存在します。

C# (.NET) のMath.Abs()メソッドではOverflowException例外がスローされます。

JavaMath.abs()メソッドでは入力と同じ値を返します。

C/C++では、関数呼び出し側が入力の範囲を保証するべき(オーバーヘッドを最小化するために関数内部での入力チェックを省く)、という設計思想の関数が多いんですが、いちいちアプリケーションコードで入力チェックするラッパーを書くのもダルいので、C/C++でもsafe_abs()みたいな関数を標準化して欲しいですね。
成否をbool型またはerrno_t型の戻り値で返して、成功すれば絶対値を引数T& or T*で返すとか。あるいはC++17で追加されたstd::optionalを使って戻り値として返す設計でも良いと思います。
整数オーバーフローが発生すると、以後の計算結果が不正になる可能性が高いので、いっそのこと.NETのように例外を投げてしまい、強制的に処理を中断するというのもアリだと思います。以下ではJavaでラッパーメソッドsafeAbs()を実装して例外処理する手法が紹介されています。

ちなみにC++20からは、ついに符号付き整数型が2の補数表現であることが規定されました。現実がまったく見えていない、旧世紀に生きているC++標準化委員会の干からびた老人どもがようやく重い腰を上げた、といったところですが、JavaC#に対して実に20年以上遅れていましたね*1

Cの最新規格C17 (C18) では今のところ規定されていませんが、次期標準規格 C2x では2の補数表現のみが許容されるようになることが N2412 によって提案されているそうです。

今後、C言語でも2の補数表現が規定されるようになったら、少なくともJavaのように、絶対値関数が返す値を規定して未定義動作を排除するか、あるいは返す値を規定した標準ラッパーを定義して欲しいところです。

*1:C/C++Unicodeサポートもかなり遅れています。JavaC#はともに20年以上前の登場当初からUTF-16を標準サポートしていたのに、C/C++では未だにchar16_t文字列を標準出力することすらままなりません。時代遅れとかいうレベルを超越しています。UTF-8リテラルの型も結局charから後出しのchar8_tに変更されるなど、最近は仕様策定ミスを撤回するために互換性を破壊する仕様変更が頻繁に入るようになりました。ちょっと考えれば分かりそうなことなのに、標準化委員会は何も見えていない無能集団以外の何物でもありません。自称・C++のエキスパートらしいですが、現役のプログラマーやエンジニアですらないダボハゼ連中です。

日本語のIT関係記事は提灯であふれている

日本(日本語)のIT関係記事は、意図的に事実を捻じ曲げ、読者に誤解をさせるような偏向的な眉唾記事であふれています。すべてステークホルダーへの忖度です。

個別のテクノロジーに精通している人間でなくとも、海外ベンダーが英語で公式に発信している原文(一次情報)に触れれば、ライター連中が日本語で書いていることが嘘八百であることにすぐ気づくのですが、日本人は英語ができないため、英語の一次情報にほとんど触れようとしない*1ことから、簡単にだませます。

pcnomori.blog.fc2.com

最近見た記事では、Apple M1に関する笠原一輝の記事(↓)が一番ひどかったですね。低俗な日本のメディアによくある、典型的な釣りタイトルです。連中にとっては情報の正確性よりもPV数のほうが大事なんでしょう。
特にコイツのベンチマークGPUとグラフィックスAPIを知っている人間からすれば噴飯ものです。Windows+OpenGLMac+Metalで比較するとか、意図的にMac側に有利な条件でテストしておいて、このタイトルですからね。そもそも中学生でも知っているような対照実験の原則を完全に無視しています。
Appleから金をつかまされてクソみたいな提灯記事を書いているのか、それともこの笠原一輝がただのApple信者なのかは知りませんが、こんなひどいバイアス記事を書いて金をかせいでいるクズが日本にいて、さらにそれを盲目的に信じる情報弱者が少なからずいるのかと思うと情けなくなります。

pc.watch.impress.co.jp

*1:実際はライティングはともかくリーディングに関しては高校卒業レベルでも大抵なんとかなるはずで、読めるはずなのに読もうとしないだけです。要するにただの英語アレルギーですね。

横浜・林、帯状疱疹で退場

なんだこの無能。ロクに仕事をしないどころか、このタイミングで貴重な医療リソースを無駄遣いするなど、言語道断。
早く消えてくださいこのカジノキチガイ脳。

なんでこんなゴミクズみたいな程度の低いクソザコ老害が市長になれるかっていうと、横浜市民の大半が同様に利権まみれのゴミクズだからです。
自民とか公明とかの看板が近所の民家のあちこちに立っていて本当に気持ち悪い。

あんたら……「自覚して生きている人たち」……ですよね?
こんなクソ政党どもの看板を掲げるっていうことは、

私、無知無能の奴隷です\(^q^)/ アゥアゥ
私のおうちをつぶして原発作ってください\(^q^)/ アゥアゥ
増税バンザーイ\(^q^)/ アゥアゥアゥッ

と言ってるようなもんだっていうことを「自覚して生きている人たち」ですよね?

道案内は冷静に対処しよう

道路を歩いていると、ときおり誰かから道を聞かれることがあります。駅で電車の乗り場や方向・停車駅を聞かれることもあります。話しかけやすいオーラでも出ているんでしょうか。

うまく道案内できたときもあるんですが、間違って反対側を教えてしまったことが何度かあります。ずいぶん昔のことであっても、そういう失敗はいまだに覚えています。つい先日もやらかしてしまいました。罪悪感と自己嫌悪に陥っています。教会で懺悔したい気分です。近所の寺でもいいんだろうか。

後悔先に立たず、ここはまず文書化することで要点を整理できるはず。
二度と同じ間違いを繰り返さないよう、懺悔も兼ねてケーススタディとして明文化しておきたいと思います。

失敗事例1:実家

実家は広島県のド田舎にあるんですが、中学で転居・高校で親元を離れたこともあって、実家でありながらあまり地理には詳しくありません。
学生の頃、確か20年くらい前のことでした。近所を散歩していたとき、乗用車を運転してきた男性から分かれ道で方向を尋ねられたんですが、誤って(よく似た地名の)反対方向の道を教えてしまったことがあります。数秒後に間違いに気づいたときにはすでに遅し。
当時はGoogle Mapはおろかカーナビもほとんど普及していない時代だったし、人もまばらな過疎地なので、あの後おそらく道に迷って苦労されたんではないかと思うと、未だに罪悪感をおぼえます。本当に申し訳ない。

教訓1

どうすれば間違いを防ぐことができたのか、よく分かりません。クルマに同乗して案内することはさすがにできないものの、せめて紙に文字で書いてくれていれば間違わなかったかもしれません。
案内する側の教訓としては、よく似た地名を混同しないように冷静にヒアリングすること、でしょうか。
今はほとんどのクルマにカーナビが装備されているので迷うことはないと思うのですが、うちの実家は相変わらず携帯電話の電波がほとんど届かない土地です。
案内される側の教訓として、不慣れな土地をドライブされる方は、自分のように地元の人間なのに間違った道案内をしてしまうアホがいること、またド田舎ではインターネットなぞ頼りにならないので、GPSベースのカーナビは必須(Google Mapのようなインターネットベースのショボいナビは絶対ダメ)ということは肝に銘じておかれたほうがよいかと。

失敗事例2:街中

つい先日ですが、神奈川県内の最寄の駅で年配の方からタクシー乗り場を聞かれました。駅には複数のタクシー乗り場があり、とっさによく知っている乗り場のほうを答えたのですが、人通りや停車数が少ないほうを間違って教えてしまいました。
10年も住んでいるのに何をやっているのか……本当にアホな案内をしました。すぐあとで気づいたんですが、人通りが多いほうにはタクシーが数台待っていて、そちらを案内しておけば即座に乗れたであろうに……

教訓2

間違いに気づいたら早めに訂正しましょう。歩くのが遅い年配の方であれば間に合う可能性が高いです。罪悪感で寝覚めが悪くなり、精神的に不安定になることに比べたら、10分や20分程度のロスなど大したことではありません。
また、方向を教えるだけではなく、近くであればその場所まで同行するとなお良しです。ただし女性が男性についていくのは危険も伴うので難しいところです。もし駅や交番が近くにあれば、そこまで同行して、あとは駅員や警察官の方々に任せるのがベストです。信頼できる職務の方々に任せれば、あとは罪悪感に陥る必要はありません。

成功事例1:大船駅

5年ほど前の話です。大船駅の西口付近で道を聞かれたことがありました。行き先を聞いてネットで調べたところ、湘南モノレールの駅だろう、ということが判明。おそらく中国系の人で、日本語は多少話せる程度、英語も通じるようでしたが、口頭で案内するには難しかったため、モノレール乗り場まで同行しました。
転職前の勤務先は大船駅近くで、当時会社に向かう途中でしたが、そもそも盛大に遅刻していたので、どうせ遅れるのであれば人助けしていこう、という気持ちでいたことが良かったのかもしれません。

総論

自分自身が不慣れな土地で突然聞かれたのであれば道案内に失敗するのも仕方ないこともありますが、地元や近所で道案内に失敗するのは痛恨の極み以外の何物でもありません。
よく知った土地であっても、記憶が曖昧であれば、いったんネットで検索して情報を補強します。冷静さを取り戻すきっかけにもなります。

ボーっと生きていると、毎日通る道にあるものにすら気づきません。もっと心に余裕を持ち、観察力を鍛えましょう。

KDDIは潰れるべきクソ企業

DMM通販の配送待ちで待機していたのでついついドアを開けてしまったんですが、インターホン越しに映像確認しておくべきだったと後悔しました。

こういう気持ち悪い訪問営業が来て回線のことを遠回しに根掘り葉掘り聞こうとしてきます。答える義務は一切ないので追い返しましょう。
CMも気持ち悪ければ営業も気持ち悪い。吐き気がするクソ企業。

togetter.com

セキュリティ意識ゼロのdocomoも死ねばいい企業の筆頭だけど、KDDIは真っ先に潰れるべき。
ソフトバンク光も電話営業がしつこいんですが、発信元の電話番号からネットで素性を調べて着信拒否すればどうってことありません。
ていうかこの3大キャリアどもはつくづく顧客をバカにしてますね。死ねばいいのに。

国連を脱退する必要はない(あるいはなかった)

「国連(国際連合)はその役目を果たしていない! 日本は脱退すべきだ!」
とかいう勇ましいことをのたまう人間が湧いて、それに賛同するアホも湧いてますがね。いつの時代も変わらんアホがいるもんだと思いますわ。先の大戦からなんにも学んどらんのかと。そりゃ永遠に敗戦国扱いです。

www.cnn.co.jp

1933年(昭和8年)、日本は国際連盟を脱退しました。日露戦争で得た中国・満州の利権を手放したくなかったからです。その結果、どうなったか。まともに歴史を学んだ読者であれば多くを語る必要はないでしょう。
他に選択肢がなかった? 追い詰められてアメリカ相手に開戦せざるを得なかった? お笑い草ですね。
ちなみにジュネーブ会議に出席して国際連盟脱退の中心的役割を担った外務大臣松岡洋右は、大日本帝国国民から賞賛され、凱旋帰国したそうです。いやあ、国民もアホでした。極右団体の発行した日本新聞なんぞに洗脳される国民性でしたからね。たぶん日本人の本質というものは今も変わっとらんのでしょう。

テドロスのような傀儡の俗物をトップに据える今のWHOには俺も疑問を持ちますがね、だからといって国連(国際連合)を脱退するというのはただの暴論だし本末転倒でしょう。何を寝ぼけたこと言っとるのかと。