Visual Studio 2015 および Visual C++ 2017 のリンク時のコード生成における最適化の不具合について

こんにちは、Visual Studio サポート チームです。 今回は、Visual C++ 2015 および Visual C++ 2017 で確認されている、C++ プロジェクトのリンク時のコード生成における最適化の不具合についてご案内します。 なお、この事象については報告が非常に少なく現在も修正に向けて調査中ですが、進展があり次第この記事を更新する予定です。   現象 以下の条件を満たす場合に、仮想関数呼び出しが正常に行われず基底クラスのメンバー関数が実行される場合があります。 速度優先の最適化 (/O2 オプションもしくは /Ox オプション) を指定している。 リンク時のコード生成 (/LTCG オプション) を指定している。 プログラム全体の最適化 (/GL オプション) を指定している。 仮想関数の呼び出しと仮想関数の実装が異なるバイナリ間で行われている。   原因 本現象は弊社製品の不具合に起因して発生しています。 Visual C++ コンパイラーおよびリンカーは、呼び出される仮想関数がコード生成時に静的に決定でき、かつ最適化によるパフォーマンスの向上が見込めると判断した場合、devirtualization と呼ばれる仮想関数呼び出しを直接呼び出しに置き換える最適化を行います。 リンク時のコード生成が指定されている場合、仮想関数の呼び出しと仮想関数の実装が異なるバイナリ間で行われている場合も devirtualization が試みられますが、仮想関数ではなく基底クラスの関数が呼び出されるコードが生成される場合があります。   回避策 以下のいずれかの方法でリンク時のコード生成における devirtualization の最適化を無効化することで、この問題を回避できます。 コンパイラー オプションで /d2notypeopt を指定する リンカー オプションで /d2:-notypeopt オプションを指定する…


Visual C++ 2015 以降のバージョンの再頒布可能パッケージにおけるインストールの前提条件

こんにちは、Visual Studio サポート チームです。 今回は、最近多くのお客様からお問い合わせをいただいている Visual C++ 再頒布可能パッケージのインストールに必要な前提条件についてご案内します。   以前のブログ記事でもご案内していますが、Visual C++ 2015 以降のバージョンの C ランタイム (CRT) は、汎用 C ランタイム (UCRT : Universal C Runtime) とそれ以外のランタイムで構成されています。Visual C++ 2015 再頒布可能パッケージをインストールすると、これらのランタイムがすべてインストールされます。 ここで、UCRT は Windows 10 以降の OS は既定でインストールされているものになりますが、Windows 10 より前の OS にインストールするためには、対象の環境に前提となる KB が適用されている必要があります。 このため、例えば、新規にセットアップしたばかりの Windows 8.1 に Visual C++ 2015 再頒布可能パッケージをインストールしようとすると、UCRT の前提条件となる KB が適用されていないために、インストール エラーとなることが想定されます。 Visual C++…


リソース エディター上で ActiveX コントロールのメニューが表示されない現象について

こんにちは、Visual Studio サポートチームです。 今回は、Visual C++ 6.0 では使用できていたものの、現行の Visual C++ では使用できなくなっている機能の一つについてご案内します。   リソース編集時の ActiveX コントロールのメニューについて Visual C++ 6.0 では、リソース エディターを使用したダイアログ リソースの編集時に、ダイアログに配置された ActiveX コントロールを右クリックすることで、コンテキスト メニューに対応する Verb 表示することが可能となっていました。また、同様の機能は、現行バージョンの Visual Studio における .NET Framework アプリケーションの Windows Form のデザイン画面でも利用可能です。 しかしながら、現行バージョンの Visual C++ のリソース エディターではこの機能が廃止されており、ActiveX コントロール側で適切に EnumVerbs メソッドを実装していた場合であっても、メニューに表示することができなくなっています。このため、編集時に利用可能なメニューとして ActiveX コントロールが提供していた拡張機能などが使用できない場合があります。 この動作は、ActiveX コントロール側の実装の問題などではなく、Visual C++ における機能の廃止に起因しています。また、現在のところ リソース エディターで本機能が改めて提供される予定はありません。 Visual C++ 6.0 で本機能を利用されていたご利用者様や ActiveX…


CDatabase クラスで発生するメモリ リークの問題について

こんにちは、Visual Studio サポート チームです。 今回は、MFC の CDatabase クラスを特定の方法で使用した場合に発生するメモリ リークの問題についてご案内します。この現象は、Visual Studio 2012 以降のバージョンに含まれる MFC で発生します。   現象 CDatabase クラスの同一のオブジェクトに対して OpenEx メソッドと Close メソッドを使用するとメモリ リークが発生し、メモリ使用量が増加し続けます。   原因 この現象は Visual Studio 2012 で追加された、CDatabase クラスの接続文字列の暗号化を行う処理に起因しています。 OpenEx メソッドで接続文字列を暗号化するためのメモリが割り当てられますが、再度 OpenEx メソッドが呼び出された際にメモリを解放せず、新たに割り当てを行っていました。 なお、弊社ではこの問題を MFC の不具合と認識しており、Visual Studio の将来のバージョンで修正を検討しています。 弊社製品の不具合によりご迷惑をおかけし、大変申し訳ございません。   対処方法 以下のいずれかの方法により、メモリ リークの問題に対処することが可能です。 同一のオブジェクトに対して OpenEx メソッドを複数呼び出さないようにする。(OpenEx メソッドで割り当てたメモリはデストラクタで解放されます。) CDatabase クラスを継承し、OpenEx メソッドを修正する。 上記 2. の具体的な実装例を以下にご案内いたします。…


Visual Studio 2015 / 2017 で発生する可能性がある _snscanf_s 関数の問題について

こんにちは、Visual Studio サポート チームです。 今回は、Visual Studio 2015 / 2017 で発生する可能性がある _snscanf_s 関数の問題とその影響についてご案内します。 この問題は以下のように Stack Overflow でも報告されておりましたが、この度、複数のお客様から弊社へお問い合わせをいただきましたので本ブログでもご紹介させていただきます。より多くの開発者様のお役に立てましたら幸いです。   VC2015で、double変数ddx_textのトラブル https://ja.stackoverflow.com/questions/16592/vc2015%E3%81%A7-double%E5%A4%89%E6%95%B0ddx-text%E3%81%AE%E3%83%88%E3%83%A9%E3%83%96%E3%83%AB   現象 _snscanf_s 関数で浮動小数点書式を指定した場合、先頭が ‘0’ で始まる場合に終端文字 ‘\0’ が正しく扱われず、_snscanf_s 関数に指定した文字数全体に対して解析が行われます。例えば、文字配列の内容が “0\02\0” であった場合、_snscanf_s 関数で期待される結果は 0 ですが、不具合により実際には 2 が返されます。 また、MFC ライブラリの DDX_Text 関数では内部で _snscanf_s 関数を使用しているため、この問題の影響を受けて、入力した値と異なる値が浮動小数点型変数に格納される可能性があります。エディット コントロールに “0” を入力した場合、文字列バッファの “0\0” 以降の値はスタックの状態によって不定となるため、DDX_Text 関数で変数に格納される値も不定となります。   原因 Visual Studio 2015 以降で利用されている新しい C ランタイム…


Visual Studio 2017 で Visual C++ ”14” ランタイム ライブラリをインストーラーに含めた場合に発生する問題について (2)

こんにちは、Visual Studio サポート チームです。 今回は、先日ご案内した以下の記事に関連して、新しいバージョンのVisual C++ ランタイム ライブラリをご利用される際に発生する可能性がある問題とその対処方法をご案内いたします。   Visual Studio 2017 で Visual C++ “14” ランタイム ライブラリをインストーラーに含めた場合に発生する問題について https://blogs.msdn.microsoft.com/jpvsblog/2017/06/22/vs2017-vc14-installer/   現象 作成したパッケージに含まれる Visual C++ “14” ランタイム ライブラリよりも、さらに新しいバージョンの Visual C++ “14” ランタイム ライブラリが既にインストールされているにもかかわらず、インストーラーの実行時にランタイム ライブラリのインストールが求められる。   原因 Visual C++ ランタイム ライブラリ用の Product.xml では、対象の製品がインストールされているかどうかの検証に Product Code を使用します。 この検証では、対象の Product Code の製品がインストールされているかどうかを調べますが、Visual C++ ランタイム ライブラリはアップデートごとに新しい Product Code を採番しているため、インストール対象のランタイム ライブラリよりも新しいバージョンのライブラリが既にインストールされていたとしても、それらは検出されないため、ライブラリのインストールが必要と判断される動作となります。…


Visual C++ 2010 の setlocale 関数の問題について

こんにちは、Visual Studio サポート チームです。 今回は、Visual C++ 2010 で確認されている setlocale 関数の問題と対処方法についてご案内します。なお、本問題は Visual C++ 2012 以降のバージョンでは修正されています。   現象 Visual C++ 2010 の setlocale 関数において、以下のような現象が発生する場合があります。   a) 引数に不正なロケール (例 : “Japanese_Japan.9326389”) を指定しても、NULL ポインターが返却されない b) 上記 a) の問題が発生した状態から、正しいロケールを指定して setlocale 関数を実行しても、処理に失敗して NULL ポインターが返却される   原因 本現象は Visual C++ 2010 の setlocale 関数の不具合に起因して発生しています。製品の不具合でご迷惑をおかけしておりますこと深くお詫び申し上げます。本不具合は Visual C++ 2012 以降のバージョンの製品では修正されています。   対処策 a) の問題については、正しいロケールを指定するようアプリケーションを修正してください。ロケールの詳細については以下のドキュメントをご参照ください。…


Visual C++ の同時実行ランタイムを利用するアプリケーションがハングアップする問題について

こんにちは、Visual Studio サポート チームです。 今回は、Visual C++ で提供されている同時実行ランタイム (ConcRT : Concurrency Runtime) で確認されている問題と対処方法についてご案内します。この問題は Visual C++ 2010、2012、2013 で発生する可能性がありますが、Visual C++ 2015 以降では発生しません。   現象 ConcRT を使用するアプリケーションで、EnterCriticalSection 関数など、Win32 の同期オブジェクトを直接使用する処理を行うと、スレッド間でデッドロックが発生して、プログラムがハングアップする場合があります。   原因 Visual C++ 2013 以前の ConcRT では、Win32 の同期オブジェクトを直接利用しない形で内部の同期処理を実現していました。 この関係で、アプリケーション側のコードで Win32 の同期オブジェクトを直接使用すると、ConcRT 内の同期処理と アプリケーションで実装した同期処理の間でデッドロックが発生する場合があります。   対処方法 Visual C++ 2015 以降の ConcRT では同期処理の実装が見直され、Win32 の同期オブジェクトを直接的に利用する方法で統一されているため、この問題は発生しません。このため、可能であれば Visual C++ 2015 以降のバージョンへのバージョン アップをご検討ください。 バージョン アップを行うことが難しい場合は、Win32…


Visual C++ 2015 でマルチバイト文字セットを利用するとコマンドライン引数を正しく取得できない

こんにちは、Visual Studioサポートチームです。 今回は、Visual Studio 2015 で マルチバイト文字セット (MBCS) を利用する際に確認されている問題についてご案内します。   現象 マルチバイト文字セット (MBCS) を利用した Visual C++ アプリケーションにおいて、コマンドラインの引数の最初の文字にマルチバイト文字がある場合に、WinMain 関数内で正しく引数を取得できない事象が確認されています。 引数の最初の文字が 1 バイト文字である場合には、正しく引数を得られますが、引数に漢字などのマルチバイト文字が利用されている場合、正しく引数を取得することができない場合があります。 マイクロソフトでは、本現象を Visual C++ 2015 のランタイム ライブラリ (ユニバーサル CRT) の問題として認識しており、調査を行っております。   対処方法 本現象は MBCS 固有の問題であるため、プロジェクトで使用する文字セットとして Unicode を利用した場合は、本現象は発生しません。 Unicode を利用することができない場合は、別途、GetCommandLine 関数を使用して引数を取得することができます。 なお、MBCS は既に非推奨となっているため、可能な限り Unicode への移行をご検討ください。   マルチバイト文字セット (MBCS) のサポート(日本語訳) https://msdn.microsoft.com/ja-jp/library/5z097dxa.aspx(英語原文) https://msdn.microsoft.com/en-us/library/5z097dxa.aspx   MBCS のまま対応する方法として、対応例 を2つ紹介します。  …


Visual C++ 2015 アプリケーションでの CRT ローカル配置について

こんにちは。Visual Studio サポート チームです。 8 月 2 日に Windows 10 の大型アップデートである Anniversary Update がリリースされ、本格的に Windows 10 の導入を進められている企業様も多いかと思います。 今回は、Windows 10 にも関係する Visual C++ 2015 のランタイムの変更点についてご紹介します。 ユニバーサル C ランタイム ライブラリについて Visual C++ 2015 では C ランタイム (CRT) ライブラリが大きくリファクタリングされ、Universal CRT (UCRT) とそれ以外のランタイム (vcruntime140.dll など) の 2 種類で構成されています。 UCRT には広く利用される標準的な C ランタイム ライブラリのコードが実装されており、安定した API を備えているため Visual Studio のリリースごとにバージョン変更する必要のない、Windows OS…