Re: Windows Vista 問題改め msvcr8x, msvcr9x 問題2008年03月07日 22時35分29秒

msvcr[89]x 問題ですが、この CRT のソースは VC++ に付いています。 (エディションにもよりますが)

それで少しソース見てみると、VC8 の wild.c はこのようになっていました。 (VC9 も同等)

#ifdef WPRFLAG
        for (argv = __wargv; *argv; argv++) /* for each arg... */
#else  /* WPRFLAG */
        for (argv = __argv; *argv; argv++)  /* for each arg... */
#endif  /* WPRFLAG */
                {
            *(*argv)++; // the first character of the argument is dropped
            /*
               - native case: all the arguments that were not within quotes
               in the command line have their first character duplicated.
               - native/managed case: all the arguments that were within quotes
               in the command line "arrive" here without the ending quote.
               - managed case: all the arguments that were not within quotes
               in the command line "arrive" here with a starting quote.
               The algorithm was initially designed not to expand the arguments
               within quotes and this is the reason for the first added character
               (to check if an expansion is desired and to be removed after that).
               In future this character will not be added anymore, but until there
               will be decided so, it must still be removed.
            */

            // if wild required --> expand, else only add.
                if (wchar = _tcspbrk( *argv, WILDSTRING)) {
                if (tmatch( *argv, wchar )) return (-1);
                }
            else {
                if (tadd(*argv)) return (-1);
            }
        }

ちなみに VC7 では次の通りです。

#ifdef WPRFLAG
        for (argv = __wargv; *argv; argv++) /* for each arg... */
#else  /* WPRFLAG */
        for (argv = __argv; *argv; argv++)  /* for each arg... */
#endif  /* WPRFLAG */
            if ( *(*argv)++ == QUOTECHAR )
                /* strip leading quote from quoted arg */
            {
                if (tadd(*argv))
                    return(-1);
            }
            else if (wchar = _tcspbrk( *argv, WILDSTRING )) {
                /* attempt to expand arg with wildcard */
                if (tmatch( *argv, wchar ))
                    return(-1);
            }
            else if (tadd( *argv )) /* normal arg, just add */
                return(-1);

どうやら managed に対応するために処理がテキトウだったようです。(泣)

従来は引数の1文字目がダブルクォートの場合、ワイルドカードのマッチング処理を行わずダブルクォートの中身を引数にしてプログラムに渡していました。

VC[89]では、1文字目を無条件で捨てて、引数にワイルドカード文字"*?"が含まれる場合はマッチング処理を必ず行うようになっています。 マッチングで一致しない場合はそのまま引数にしてプログラムに渡しますが、マッチングが一致した場合はワイルドカードが展開されてプログラムに渡されてしまいます。

つまり、ワイルドカード文字が引数に含まれる場合は、ダブルクォートで囲もうと、ワイルドカード展開が起こるということです。 ダブルクォートは空白文字(スペースとタブ)を引数に含める場合にしか意味をなしません。

これは仕様変更というよりは、バグでしょう。

もちろんこれは setargv.obj をリンクし、引数のワイルドカード展開を行った場合の話です。 setargv.obj をリンクせず、引数のワイルドカード展開を行わない場合には関係のない話です。

namazu.exe もワイルドカード展開を行わなければ問題なく使えます。 その場合は、引数に指定するインデックスをワイルドカードで指定できなくなってしまいます。

ただ、インデックスの指定にワイルドカードが使えないということを引き換えにしてでも、古い VC++ 6.0 から VC++ 2005(VC8), VC++2008(VC9) に切り替える方が x64 対応等を考えると良い気もしてきました。

コメント

_ opengl2772 ― 2008年03月08日 05時34分57秒

http://msdn2.microsoft.com/ja-jp/library/bb384633.aspx

Visual C++: はじめに
「互換性に影響する CRT の変更点」にしっかり書かれていることに気付きました。

「Setargv.obj または Wsetargv.obj とリンクしている場合、コマンド ラインでワイルドカード文字が展開されます。従来は、二重引用符で囲むことによってワイルドカード文字の展開を抑制できましたが、今後、この方法で抑制することはできません。詳細については、「Expanding Wildcard Arguments」を参照してください。」

managed のために仕様の方を変えるってことですか...。

コメントをどうぞ

※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。

※なお、送られたコメントはブログの管理者が確認するまで公開されません。

名前:
メールアドレス:
URL:
コメント:

トラックバック

このエントリのトラックバックURL: http://namazu.asablo.jp/blog/2008/03/07/2708668/tb

※なお、送られたトラックバックはブログの管理者が確認するまで公開されません。

_ ナマズのブログ - 2008年03月11日 17時42分17秒

結局、Visual C++ 2005 を使って namazu.exe をコンパイルする方針に変更しました。

これにより従来の VC++6.0 でコンパイル + setargv.obj をリンクした namazu.exe とは動作が異なります。

以後、