プログラマのつれづれなるままにプログラマのつれづれなるままに音宮志久が思ったことなどをネタにします。プログラムネタ・数学ネタがメインです。*)0らしいコメントを残すちょっとtwitter上でNULLに関することをつぶやきましたが、ツッコミが帰ってきてしまったため気になって仕様書(C89およびC99のもの)を読み込んでみました。すべての論理をつなげてみると次のような結論となりました。*にキャストしたものがNULLとして定義される、と。仕様書にはどう書いてあったか、というと・・・C89でもC99でも記述は同じなのでそれは置いておいて。pointerおよびそれに関わる用語の定義です。関わる部分だけざっくりと翻訳すると次のようになります。*)0として定義する」という結論が得られるわけです。3行目の説明を読んでみると、「何も指さないことが保証されている」という参考書の説明とは微妙に食い違っているように見えるのですが...。細かいことをいうなら特定のメモリ空間をオブジェクトに含めるのかどうか?というところでしょうか。*)0をキャストしてアクセスすると特定の読み書きとして成立するシステムもあるとのことでした。前者は48bitアドレスというなかなか変わった方式のものですし、後者は仮想メモリやメモリ保護の概念がない時代のものですので、今の時代には全くそぐわないものですから無視してもよいかもしれません。pointerのとき」の意味になるようです。pointerによるifの判定にも誤りはない」という結論になりました。仕様書を読んでみるといろいろな動作についてちゃんと定義が書いてあるので、これに従ったコンパイラを完全に作るのは確かに大変だな、という感想もあります。逆にNULLをポインタにキャストしてアクセスした場合常にメモリ保護例外などのエラーとなるとは限らない、というのは調べていてびっくりした点です。今のシステムではほぼあり得ないことですが、昔のメモリ空間がカツカツだったりする環境のためなのでしょうかね。pointerとして扱われるようです。NULLは上記の定義より整数型としての値を持つことがあり、引数として整数型とポインタ型のオーバーロードがあった場合にNULLを指定すると誤って整数型を引数とする方が呼び出されてしまう、という問題が起こってしまいます。pointerで呼び出していることを示すものということでした。いえば昔この手の問題で悩まされたことがあったな~と懐かしみながら。Captcha)コメントを残すというわけで、Captchaが大分バグっている、というかとある事情で不具合が起こっていたようなので更新しました。その更新について少し書いておきたいと思います。一応コメントの書き込みテストはしているのでキャッシュ処理に関する問題はないはずですが...。大量のスパムコメントがあった理由は...4月までの数年間WordPressの更新は「緊急性の高いものを除きとりあえずセキュリティアップデートだけ」という状態だったので、一部の事態に鈍感になっていたことが大きかったです。本題の大量のスパムコメントですが、とりあえずコメントのフィルタシステムでスパム扱いされていたので半分無視していたのですが、妙に気になったのでCaptchaに関して調べてみると・・・。Anti-SpamとCaptchaは問題ありという内容の記事があり、調べてみると開発者が変わって更新が止まっているとかバックドアが仕込まれているとかいろいろと情報がありました。Anti-Spamの方で、どうもこれがスパムコメントの原因だったようです。Captchaになりました。基本的にこれらはすべてGoogleのCaptchaシステムを借りて行うものなので変に所有者が変わらない限りはCaptchaとしての動きはほぼ変わりません。Captchaを使ってみることにしました。導入の手順はおそらくこの3つともほとんど変わらない(と思う)というのも、結局はGoogleのreCAPTCHAを借りることになるため、WordPressの管理画面からプラグインを検索してインストールするGoogleのreCAPTCHAの管理画面にGoogleアカウントでログインしてAPIキーとSecretキーを取得する設定画面でAPIキーとSecretキーを登録して、ほか必要な設定を行うとなります。GoogleからAPIキーを取得するためのアドレスは大抵プラグインの設定画面にリンクが張られていると思うのでそれを参照すればよいと思います。注意が必要なのが、reCAPTCHAのキーを取得するときに認証のバージョンなどを設定することができますが、そのバージョンにプラグイン側の設定も合わせる必要がある、ということです。Captcha)で設定する場合とv3で設定する場合でそれぞれ方法が異なりますので注意しましょう。あとはどの場所にCaptchaを設置するかどうかです。Captchaではいくつかの場所にチェックボックスだけで設定できるので、コメント投稿およびログイン画面に設定することにしました。これで安全性がかなり高まるかと思います。Captchaの場合はbbPressやBuddyPress、WooCommerceとも連動させてCaptchaをかけることができるので、これらのプラグインでサイトを作っている人には簡単に設定できるようになる分おすすめかもしれません。Captchaのプラグインを変えるだけでスパムコメントが一切なくなった...というわけで、Captchaのプラグインを変えて数日間たったわけですが、スパムコメントが一切なくなりました。このサイトこの2年間くらい記事更新がほとんどなかったこともありコメントらしいコメントもないので正しいコメントが受け付けられているかどうかはテストしたこと以上のことは不明なのですが、それでも管理の手間が大分減っているのでちょっと感動です。スパムコメントのフィルタリングに関してはIPフィルタ以上の効果ですね。志久WindowsのDPIスケーリング処理について一考察コメントを残すWindowModePatchで実装するのに大分困っていたDPIスケーリング処理(DPIAwareness)についてメモ書き代わりに処理について書いておきます。ちなみに、英語の読み間違いを防ぐためにいっておくと、日本語的には「DPIによるスケーリング(解像度変更)処理」というべきなのでしょうが、英語では「DPIAwareness」となっており、Awarenessの意味は「気がつく」「知る」なので、直訳すると「DPIについてプログラム側が気がついているかどうかを処理する」という意味になってしまいます。これが私が処理について誤解した原因なのですが...。DPIスケーリングを指定する3つのモードはい、まずは私が翻訳をミスったポイントです。簡単に調べてみるとほかの日本語サイトではちょっと解説してあったのでなんともいえないのですが。基本的にはプログラム側が指定できるDPIスケーリングのモードは3つあります。aware)DPI処理を完全にアプリケーション側で行う。aware)となります。注意してほしいのが1.のUnawareパターンですが、これはつまり「アプリケーション側は何もやらなくてもシステム側(すなわちOS側)が勝手にやるので気にしなくてもいいよ」という意味です。プログラム側からこれを設定すると表示上は勝手にスケーリングしてしまうのでWindowModePatchでは非常に都合が悪いモードになっています。通常のアプリケーションでは面倒であれば1.のパターンを使うのもありだと思います。今時のゲームであれば解像度調整機能は必須なので1.のUnawareを使うことはまずないと思います。DPIスケーリング処理は通常はマニフェスト側で設定するMicrosoft側としてはこちらを想定しているようです。いうのも、この後愚痴のように出てきますがアプリケーションが起動してからだとスケーリングモードの変更がプロセス単位でできないことが多いのです。(これについては推察になりますが、おそらくWindowModePatchと同じように座標を設定/取得する関数の処理をスケーリングに合わせて変更する、というものが割り込むことが「想定されるのか否か」によって初期化の方法が変わるのために難しいのではないか?というものです。)まあ、通常のアプリケーションならマニフェスト指定が簡単でしょうね。やり方としてはVisualStudioなどのビルドツールにおいてマニフェストの設定で「DPIの認識」を設定するマニフェスト内のwindowSettingsセクション内にdpiAware値およびdpiAwareness値を設定するというものです。前者の方が勝手に作ってくれる分簡単ですね。マニフェストにDPIに関する設定がないときはシステム側が勝手にスケーリングをするDPIUnaware状態となりますので注意してください。アプリケーション側からの設定はOSごとに方法が異なるまず紹介されている方法として自身のプロセス全体にDPIに関する設定をかける方法。1607以降)によりできる、と書いてあるので、該当するフラグをつかって設定すれば良さそうなのですが、私がデバッグした限りにおいてこれらがうまく設定できた試しがない、というのが悲しいところでした。Denied」(すでにDPIのモードが設定されているため設定不可能)ではねられて終わりでした。~と思いながら書いています。いうわけで仕方がないので...。Win8.1以前では対応策がこれ以上ないようですが、Win10以降であればスレッド単位、もしくはウィンドウ単位でDPIAwarenessが設定できるのでそちらを使います。スレッド単位の場合はCreateWindowEx関数などウィンドウ作成系の関数の前に呼び出せばモード変更が可能なようです。使う関数はGetThreadDpiAwarenessContext関数SetThreadDpiAwarenessContext関数になります。一応Get側で取得して予定しているモード値と異なっているときSet側で設定する、という動きになります。Win10以外のOSにも対応する場合はuser32.dllにインポートされているのでたいていの場合GetModuleHandle関数からGetProcAddress関数で取得することになります。面倒なのはこれらで使うDPI_AWARENESS_CONTEXTという値です。いうのは、WindowsSDKのバージョンの関係で自分で定義する場合が多いこととこれら2つの関数が返すDPI_AWARENESS_CONTEXTの値はMSDNで定義されている各値と同じものを返さない場合がある、ということです。前者についてはDPI_AWARENESS_CONTEXTは列挙子ではなくハンドル扱い、と書かれていますのでUINT_PTR型などとしないとGetProcAddress関数で処理を持ってきたときに見事な失敗となりますし、後者はマニフェストや(この後紹介する)実行ファイルのの互換性設定でDPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2相当の値を設定してあるからといってGetThreadDpiAwarenessContext関数はMSDNでDPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2として定義されている値である(-4)ではなく別の値を返すパターンがあるということです。これが判定にはやっかいすぎる現象だと思います。設定する場合の値はMSDNの値が正しいようですが...。WindowModePatchでは前者はちゃんとハンドルとして定義する構文を借りて値を再定義していますし、後者についてはGetAwarenessFromDpiAwarenessContext関数を一度通してDPI_AWARENESS列挙子にすることでモードを判定するようにしています。この辺も実装に手間取った理由だったりします。あとは必要に応じてDPI変更時の処理を組み込むだけDPIを変更する必要がある場合はWM_DPICHANGEDメッセージがウィンドウプロシージャに飛んできますのでこれを見てウィンドウの大きさや文字の大きさなどを制御します。このあたりは今回の考察範囲からは外れますので詳しく書きません。使用者側から見るのであれば実行ファイルのプロパティから設定可能Win10系であればこれが可能です。Win8.1系でもできるかな?やり方としては対象アプリケーションの実行ファイルのプロパティを開き「互換性」タブから「高DPI設定の変更」を選択して誰がスケーリングをするのか設定が可能です。ちなみにこれを使うと単にウィンドウモード時の解像度が低いだけなら無理矢理解像度を引き上げることが可能だったりします。メニューバーまで拡大されてしまうのはご愛敬といったところですか。WindowModePatchのような自由度はないですが、OSの機能ですのでうまく使えるのであれば損はないかな~と思ったりもしています。ゲームの場合は直接解像度を見るので気にしない方がよい機能かなと思います。いっても、名前の入力などでダイアログを出す必要がある場合は対応する必要もあるかもしれません、とだけ付け加えておきましょう。Alphaを公開コメントを残す過去の記録を見てみると大体1年半ぶりの更新なんですね...。生きていますよ~という意味とビルド環境の変化に対応するための試しという意味がかなり大きいバージョンとなっています。開発環境をVisualStudio2017へと移行したためにいろいろと不具合が...今回の大きな変化がこれです。一つ前まではVisualStudio2010だったのですが、今回は最新一つ手前のVisualStudio2017でビルドを行っています。いうのも、昨年の段階でPCを組み直したときに環境をまっさらにした関係でVisualStudio2010の開発環境まで完全に吹っ飛んでしまったのが大きかったのと、その後開発環境を戻す余裕がなくなったためにどうせならとVisualStudio2017を購入したためにさらに開発環境の再構築に時間がかかってしまったのが大きかったです。実際にプロジェクトの更新だけではなくソースコードの漢字コードを変換していったり、ランタイムライブラリの動作が変更されているものがあったために対応する処理を書いたりするなどがあったためだったりします。副産物としてWindowModePatchの設定ファイルの漢字コードをUTF-8に変更しております。旧の設定ファイルであるShiftJIS形式でも読み込めますし、UNICODE形式で保存されても読み込めるようになっています。この「複数文字コードに対応したテキストファイルの読み込み処理」が作られたのがちょっと大きいです。いうフリーソフト側に使うだけではなく仕事で作成するツール類にも使えるのが非常に大きかったりします。一応DPIのスケーリング処理に「暫定的に」対応といってもやっていることは「スケーリング処理をアプリケーション側で行うように見せかけているだけ」だったりします。実際、WindowModePatchは解像度変換機能がメインなので逆に現在のモニタの解像度に合わせた設定ができないと微妙に困るからですね。Win10の初期段階のものだと設定を正しくしないとマニフェストファイルにスケーリング処理対応の方法が書かれていない場合にWinAPI側で勝手にスケーリングされて設定の数字が誤ってしまう、という現象もありましたので。Update)以降であれば(WindowModePatchが対応できれば)対応処理が入ると思います。問題はそれより古いバージョンでの動作。一応対応コードは書いておいたのでWin8.1以降であれば動いて「ほしい」コードなのですが、手元でやったいる段階では動かないことが多かったです。これについてはDPIAwarenessと呼ばれる部分の処理の説明をもう少し読み込んだ方がよいかもしれません。実際、はじめに思っていた設定値の役割が完全に逆になっていたことに気がついたのはかなり後だったりしますので。対応したソフトが増えていないだろうとは思う頑張ってDirectX5時代のDirect3Dに対応しようとした形跡が見えるコードは今のところ封印しておりますし、やりたいことも増えてきているながらやらなければならないことも増えてきていますので...。頑張って増やしていければな~と思いながら。開発環境をVisualStudio2017へ移行してみたコメントを残す最新のVS2019ではないのが悲しいですが...。MovieLayerPlayerやらWindowModePatchを再度構築できる環境を整えるためにVisualStudio2017でビルドができるようにいろいろと設定やらファイルの文字コードやらを変更していってみるといろいろと大変なことがわかってしまって「ぎゃ~~~」と言いながら作業していました...。(VS2010から見たら)だいぶ変わってしまったVS2017でした結局ビルド環境を整えなおすのに丸2日かかってしまいました。ビルドに成功したのはMovieLayerPlayerの方でWindowModePatchはまだテストしていない状態です。こちらを先にやったのはほかのライブラリのビルドなどを考えた結果なのですが...。ディレクトリの設定はVS2010と変わらずこの辺はこちらの記事を参考にできます。自分で書いて自分で忘れているのが悲しいですね...。DirectXや自分で作ったライブラリ・インクルードファイルを参照する場合はこの設定がないとちょっと厳しいので気を付けましょう。DirectXのSDKはDirectX9系だと良くてもJune2010なのでインストールしたくないため仮想マシンで一度展開して必要なものだけコピーしていますので、そのためにもディレクトリの設定は設定ファイルからやらないとまずい、ということもあったりします。ソースコードの文字コード設定には気を付けて今回文字コードをShiftJIS(CodePage932)からUNICODE系へと変更しています。面倒なのが、ソースコード(cpp,hなど)はBOM付きUTF-8へリソースファイル(rc)はUTF-16へにしないとまずいということ。ソースコードにBOMを付け忘れると勝手にShiftJISと認識されて大量のエラーが出てきますので気を付けて。codepage)を削除して文字コードをUTF-16と認識させるという作業が必要になります。rcファイルではBOM付きUTF-8は認められない様子なので気を付けてください。ライブラリを構築するときの依存性設定がさらに厄介にVS2010では依存性を持たせるだけでは自動的にリンクがされず、[共通プロパティ]=>[Frameworkと参照]で依存するプロジェクトを参照として追加する必要がある、とは書いたのですが、これがVS2017になると、ソリューションエクスプローラから対象のプロジェクトを開くとソースファイルやヘッダファイルがあるところに「参照」となぜかこちらに参照設定が来ていますのでこれで設定しましょう。こちらに参照設定をすることでライブラリがリンクされるようになります。設定ミスなのかバグなのかわからない現象にはまってしまったのが、「依存しているライブラリをリンクしてくっつける場合、依存先(つまり子)のライブラリの構築時にプリコンパイル済みヘッダが設定されているとそのライブラリを使うプログラムを構築するときにLNK2019エラーが発生してリンクに失敗する」という現象でした。複数のライブラリをまとめて一つのライブラリとして扱う場合、親以外のライブラリにプリコンパイル済みヘッダを設定しているとプログラムを作るときに失敗する、という現象になります。何か設定で回避できるのかどうかよくわかりませんが、今のところ単純な回避策は「プリコンパイルを使用しないように設定してビルドする」以外思いつかないのが現状だったり。解決法を知っている人は教えてください...。bind2ndやらmem_funやらが非推奨になっています。言うならbind2ndやmem_funがfunctionalに移ったため、そちらをインクルードしないとコンパイルに失敗する、というものですが、どうせこの機会なのでbind2ndはbindとplaceholdersの組み合わせに、mem_funはmem_fnを使ったパターンに切り替えてしまいました。bind1stやbind2ndとかの限定版よりbindの方が使いやすいのでそちらに切り替えてしまいましょう。WindowsXP以前に必要としていたルーチンはもう必要ないよね...?ということで、いくつか片づけました。GetVersionExを使っていた部分はDeprecatedとなっていますのでVersionHelperのIsWindows系関数でバージョンを判定するように変更するとか、cpuidに関するルーチンを再構築したりとか、x86系のコンパイルでSSE2はもう当たり前だと思うので一部のプロジェクトで設定するとかしています。これで早くなるかどうかはよくわかりませんが...。いくつか最新機能も取り入れてみた私の場合はWindowModePatchなどの関係もあり、解像度の設定で解像度を文字列で表す、というのをやっているので4Kが3840×2160になる、とかWindows10に関するバージョン検知なども少し書き直しています。次回のWindowModePatchのアップデートはまずはVisualStudio2017でのコンパイル版にすることと、解像度を増やすことと、あとはスケーリング処理に関する部分を入れてみることでしょうか。いってもどれだけ時間が取れるのかは未定ですが。志久プログラムネタや思いついたり世間で話題になっている数学ネタを解説したりしています。プログラマとしては今年度(つまり2020年3月)までの復帰となるか、完全復帰となるか、別の仕事に戻るかは運と実力次第。ちなみに教育系のプログラムでもOKです。アクセスカウンタアクセス数:スポンサーリンク。