none
charをCString型にキャストすると失敗する RRS feed

  • 質問

  • 以下のようにcharからCStringに変換すると、まれに失敗(!?)することがあります。
    確認用に "str" をメッセージボックスに出力しますと、失敗時は「--」とだけ表示されます。
    また、失敗した場合でも xxx001にデータをセットする部分では、正しくデータがセットされていることも確認済みです。

    ちなみに、
    今まで、EVC++3.0でビルドしたものでは再現したことがありませんが、EVC++3.0→VisualStudio2005に移行後から以下でキャストが失敗するようになりました。キャストの仕方に何か問題があるのでしょうか?

    以上、よろしくお願い致します。


    // 構造体
    struct _XXX{
      char aaa[12]
      char bbb[12]
      ・
      ・
      } XXX


    void AbcDefg()
    {
      XXX xxx001;
      CString str;

      // 構造体xxx001にデータをセットする処理
      ・・・

      // 問題のキャスト部分
      str = ((CString)xxx001.aaa).Mid(0,4) + _T("-") + ((CString)xxx001.aaa).Mid(4,4) + _T("-") + ((CString)xxx001.aaa).Mid(8,4);

    // デバッグ
    MessageBox(NULL,str,_T("str"),MB_OK);

    }

    2011年3月14日 3:45

回答

  • # char の配列を CString にキャストしようとすることにものすごく違和感を感じるのですが...。

    ちなみに文字セットは Unicode でしょうか?それともマルチ バイトでしょうか?
    キャストするのではなく、文字列を一旦 CString に格納してから処理するわけにはいかないのでしょうか?
    char の配列を文字列とみなしているはずなので、'\0' を考慮するとバッファー オーバーランなのではないかと思うのですが、大丈夫なんでしょうか?

    struct _XXX{
     char aaa[12]
     char bbb[12]
      ・
      ・
     } XXX

    str = ((CString)xxx001.aaa).Mid(0,4) + _T("-") + ((CString)xxx001.aaa).Mid(4,4) + _T("-") + ((CString)xxx001.aaa).Mid(8,4);
    • 回答としてマーク 山本春海 2011年4月4日 8:12
    2011年3月14日 4:38
  • やってることがむちゃくちゃです。書いても仕方がないですが

    CStringA str;
    str.Format( "%.4s-%.4s-%.4s", &xxx001.aaa[0], &xxx001.aaa[4], &xxx001.aaa[8] );

    • 回答としてマーク 山本春海 2011年4月4日 8:13
    2011年3月14日 5:26
  • 既に書いている事を繰り返しますが、

    動いている事がコードの正しさを証明すると考えるのは間違いです。
    少なくともキャストに関してはそのキャストが論理的に正しい事を説明できない限り、
    キャストを行なうべきではありません。
    EVC++3.0で表面化しなかった問題がVC++2005では表面化したと考えた方が自然です。

    書かれているキャストが正しいと言うのであれば、ご自身が論理的にキャストが正しい事を説明できないとおかしいです。

    重ねて書きますが、
    動いているからOKという思考は危険です。
    少なくともコードの正しさに関してきちんと論理的な説明ができる事が大前提です。
    説明はできないけれど、動いているからOKと言うのは正しい事の証明にはなりません。

    一般的な動作テストにしても基本的にコードが論理的に正しい事が前提になります。
    従ってテストでOKであることが、不具合が0である事の証明にはなりません。
    行ったテストの範囲で検出できる不具合が0である事は証明できるかもしれませんけれど。
    (それすら、実際には難しいと思いますが)

    追伸:
    実際には、メモリ上の状態等諸々の要因によって正しくないコードが綱渡りのような状態で動作し、
    結果的に期待した動作をしているケースはありえます。例えば、デバッグビルドでは動作するけれど、
    リリースビルドではプログラムが落ちてしまう等々。メモリ上の状態が変わらないと表面化しない不具合も
    ありますから、動作している事が正しいコードである事の証明にはならないのです。


    解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。
    • 回答としてマーク 山本春海 2011年4月4日 8:12
    2011年3月14日 7:54
  • 開発者が見て違和感を感じるのであれば、やはり何かが間違っていると考えるべきではないでしょうか。(コードの不吉なにおい)
    EVT++3.0 では「運悪く」動いてしまっているだけだと思うのですが。

    1万歩以上譲って、CString でキャストすることが char の配列を使って CString のコンストラクタが走るとして、(あくまでも仮定の話です)
    やはりバッファー オーバーランになっているために CString のコンストラクタに有効な文字列を渡せなくなったとか。(あくまでも仮定の話ですよ)

    正しいコードに書き直す方が、他の開発者にとっても親切だと思うのですが、そうできない理由でもあるのでしょうか?
    (どうしても原因を探りたいということであれば、CString の中までトレースすれば済む話だと思います。)

    • 回答としてマーク 山本春海 2011年4月4日 8:12
    2011年3月14日 9:06
  • >キャスト
    この方法によるcastでCStringW Objectは正しく生成されます。
    Codeを追ってもらえれば分かりますが、const char*で受けるConstructorが呼ばれ、内部でUnicodeに変換されます。

    とはいえ、現状のCodeはCStringW Objectをその度作ることになるので、効率はよくありません。
    すでに紹介されている方法に変更した方が良いです。

    UnicodeとMBCSは一文字の扱い方が異なります。その辺の処理を確認してみてください。
    例えば以下のようなCodeでは一文字の扱い方が異なることが分かります。

    CString str;
    CString str2;
    char ch[12] = "abcdefghigk";
    char ch2[12] = "あいうえおa";
    
    str = ((CString)ch).Mid(0,4) + _T("-") + ((CString)ch).Mid(4,4) + _T("-") + ((CString)ch).Mid(8,4);
    
    str2 = ((CString)ch2).Mid(0,4) + _T("-") + ((CString)ch2).Mid(4,4) + _T("-") + ((CString)ch2).Mid(8,4);
    
    

    結果
      str:abcd-efgh-igk
      str2:あいうえ-おa-

    >数十回に一回ぐらいで失敗
    必ず失敗するパターンを見つけることはできますか?
    また失敗した場合、関係する変数の中身を全てDumpして何かHintがないか探してみてください。
    再現性が不確実となると、上記以外のCodeで何か不味いところがあるのかもしれません。

    >EVC++3.0では期待どおりであるという事と、VC++2005にて失敗する場合がある
    これらの開発環境は別物である、という認識を持って望まれたほうが良いでしょう。
    Projectの設定も異なるでしょうし、MFCも開発環境が変わると仕様が変わることが結構あり、従来のCodeでは正しく動作しないこともあります。

    残念ながら現状の情報からは、これ以上判断することができません。

    • 回答としてマーク 山本春海 2011年4月4日 8:12
    2011年3月14日 9:13
  • kozzさんから提示されたような論理的な説明がないとキャストをして良いという話にはなりません。
    これを理解した上でやっているなら良いかもしれませんけれど。
    但し、C++の文字列はNULL終端が期待されているはずなので設定されている文字列がNULL終端を
    含んでいるなら正常にいきそうですが、NULL終端がないならやはりNULL終端を求めて暴走しそうです。

    で、既に指摘されている通りコンストラクタが度々動いていしまう今のコードは効率が悪いです。
    組み込み系ならなおさら推奨されないコードだと思います。
    基本的には一旦CStringのワーク変数に設定して処理を行うべきですが、
    構造体がNULL終端を意識していないのであれば、一旦NULL終端がある文字列の状態にしてから
    ワーク変数に設定して以降はワーク変数で処理するという事になると思います。

    NULL終端を探して暴走している場合、どんな結果になるのかは神のみぞ知るではないかと思いますけれど。
    CStringのコードを一々最後まで追いかければどうなっているかわかるかもしれませんけれど、
    そこまでするまでもなく、まずいと思います。


    解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。
    • 回答としてマーク 山本春海 2011年4月4日 8:12
    2011年3月14日 9:27

すべての返信

  • # char の配列を CString にキャストしようとすることにものすごく違和感を感じるのですが...。

    ちなみに文字セットは Unicode でしょうか?それともマルチ バイトでしょうか?
    キャストするのではなく、文字列を一旦 CString に格納してから処理するわけにはいかないのでしょうか?
    char の配列を文字列とみなしているはずなので、'\0' を考慮するとバッファー オーバーランなのではないかと思うのですが、大丈夫なんでしょうか?

    struct _XXX{
     char aaa[12]
     char bbb[12]
      ・
      ・
     } XXX

    str = ((CString)xxx001.aaa).Mid(0,4) + _T("-") + ((CString)xxx001.aaa).Mid(4,4) + _T("-") + ((CString)xxx001.aaa).Mid(8,4);
    • 回答としてマーク 山本春海 2011年4月4日 8:12
    2011年3月14日 4:38
  • やってることがむちゃくちゃです。書いても仕方がないですが

    CStringA str;
    str.Format( "%.4s-%.4s-%.4s", &xxx001.aaa[0], &xxx001.aaa[4], &xxx001.aaa[8] );

    • 回答としてマーク 山本春海 2011年4月4日 8:13
    2011年3月14日 5:26
  • まず、C言語タイプのキャストは無理やり型合わせを行ってしまうので、
    C++言語を使うのであればC++言語のキャストを使った方が良いと思います。
    そうする事である程度はエラー等が出るようになります。
    まあ、C++言語にも無理やりキャストするやり方はあるので使い方を間違っていたら
    元も子も有りませんけれど。

    C言語でも同じですけれど、

    そのキャストは本当に大丈夫なのかと言う部分に確証が無いのであれば、キャストを使うべきでは有りません。

    キャストは使う側がこのキャストは論理的に安全であるという事をわかった上で行うべきです。
    キャストしてみて動いたからこのキャストで良いという判断は誤りで、実際には正しく無いキャストでも
    たまたまうまく動いてしまうケースと言うのが実際に存在します。
    従って動いているからOKというはNGです。

    既に指摘を受けていますが、そもそも構造体XXXにセットされる文字列はNULL終端を意識しているのか?
    と言う部分はきちんと確認を取るべきではないかと思います。

    あと、素直に考えるなら一旦CString strWk = xxx001.aaa;(勿論、NULL終端している事が前提)

    str = strWk.Mid(0,4) + _T("-") + strWk.Mid(4,4) + _T("-") + strWk.Mid(8,4);

    とするのが、解りやすいと思います。

    下手に手順を端折るよりも安全だと思います。


    解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。
    2011年3月14日 6:33
  • 返信ありがとうございます。

    文字セットは UNICODE でございます。
    データをセットする処理では、テキストファイルから取得した文字列(shiftJIS)を扱っております。

    ちなみにテキストの"aaa"文字列の直後には"bbb"の文字列が連続して続いています。
    ご指摘のようにバッファー オーバーランも考えたのですが、EVC++3.0でビルドしたものは期待する値を得られます。
    VC++2005でも、期待する値が得られる物の、数十回に一回ぐらいで失敗(!?)します。

    期待「0123-3456-6789」
    失敗「--」

    たしかに、私もこのキャストに違和感を感じる部分はありますが、EVC++3.0では期待どおりであるという事と、VC++2005にて失敗する場合があるということが分からず悩んでおります。

    2011年3月14日 7:41
  • 既に書いている事を繰り返しますが、

    動いている事がコードの正しさを証明すると考えるのは間違いです。
    少なくともキャストに関してはそのキャストが論理的に正しい事を説明できない限り、
    キャストを行なうべきではありません。
    EVC++3.0で表面化しなかった問題がVC++2005では表面化したと考えた方が自然です。

    書かれているキャストが正しいと言うのであれば、ご自身が論理的にキャストが正しい事を説明できないとおかしいです。

    重ねて書きますが、
    動いているからOKという思考は危険です。
    少なくともコードの正しさに関してきちんと論理的な説明ができる事が大前提です。
    説明はできないけれど、動いているからOKと言うのは正しい事の証明にはなりません。

    一般的な動作テストにしても基本的にコードが論理的に正しい事が前提になります。
    従ってテストでOKであることが、不具合が0である事の証明にはなりません。
    行ったテストの範囲で検出できる不具合が0である事は証明できるかもしれませんけれど。
    (それすら、実際には難しいと思いますが)

    追伸:
    実際には、メモリ上の状態等諸々の要因によって正しくないコードが綱渡りのような状態で動作し、
    結果的に期待した動作をしているケースはありえます。例えば、デバッグビルドでは動作するけれど、
    リリースビルドではプログラムが落ちてしまう等々。メモリ上の状態が変わらないと表面化しない不具合も
    ありますから、動作している事が正しいコードである事の証明にはならないのです。


    解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。
    • 回答としてマーク 山本春海 2011年4月4日 8:12
    2011年3月14日 7:54
  • 開発者が見て違和感を感じるのであれば、やはり何かが間違っていると考えるべきではないでしょうか。(コードの不吉なにおい)
    EVT++3.0 では「運悪く」動いてしまっているだけだと思うのですが。

    1万歩以上譲って、CString でキャストすることが char の配列を使って CString のコンストラクタが走るとして、(あくまでも仮定の話です)
    やはりバッファー オーバーランになっているために CString のコンストラクタに有効な文字列を渡せなくなったとか。(あくまでも仮定の話ですよ)

    正しいコードに書き直す方が、他の開発者にとっても親切だと思うのですが、そうできない理由でもあるのでしょうか?
    (どうしても原因を探りたいということであれば、CString の中までトレースすれば済む話だと思います。)

    • 回答としてマーク 山本春海 2011年4月4日 8:12
    2011年3月14日 9:06
  • >キャスト
    この方法によるcastでCStringW Objectは正しく生成されます。
    Codeを追ってもらえれば分かりますが、const char*で受けるConstructorが呼ばれ、内部でUnicodeに変換されます。

    とはいえ、現状のCodeはCStringW Objectをその度作ることになるので、効率はよくありません。
    すでに紹介されている方法に変更した方が良いです。

    UnicodeとMBCSは一文字の扱い方が異なります。その辺の処理を確認してみてください。
    例えば以下のようなCodeでは一文字の扱い方が異なることが分かります。

    CString str;
    CString str2;
    char ch[12] = "abcdefghigk";
    char ch2[12] = "あいうえおa";
    
    str = ((CString)ch).Mid(0,4) + _T("-") + ((CString)ch).Mid(4,4) + _T("-") + ((CString)ch).Mid(8,4);
    
    str2 = ((CString)ch2).Mid(0,4) + _T("-") + ((CString)ch2).Mid(4,4) + _T("-") + ((CString)ch2).Mid(8,4);
    
    

    結果
      str:abcd-efgh-igk
      str2:あいうえ-おa-

    >数十回に一回ぐらいで失敗
    必ず失敗するパターンを見つけることはできますか?
    また失敗した場合、関係する変数の中身を全てDumpして何かHintがないか探してみてください。
    再現性が不確実となると、上記以外のCodeで何か不味いところがあるのかもしれません。

    >EVC++3.0では期待どおりであるという事と、VC++2005にて失敗する場合がある
    これらの開発環境は別物である、という認識を持って望まれたほうが良いでしょう。
    Projectの設定も異なるでしょうし、MFCも開発環境が変わると仕様が変わることが結構あり、従来のCodeでは正しく動作しないこともあります。

    残念ながら現状の情報からは、これ以上判断することができません。

    • 回答としてマーク 山本春海 2011年4月4日 8:12
    2011年3月14日 9:13
  • kozzさんから提示されたような論理的な説明がないとキャストをして良いという話にはなりません。
    これを理解した上でやっているなら良いかもしれませんけれど。
    但し、C++の文字列はNULL終端が期待されているはずなので設定されている文字列がNULL終端を
    含んでいるなら正常にいきそうですが、NULL終端がないならやはりNULL終端を求めて暴走しそうです。

    で、既に指摘されている通りコンストラクタが度々動いていしまう今のコードは効率が悪いです。
    組み込み系ならなおさら推奨されないコードだと思います。
    基本的には一旦CStringのワーク変数に設定して処理を行うべきですが、
    構造体がNULL終端を意識していないのであれば、一旦NULL終端がある文字列の状態にしてから
    ワーク変数に設定して以降はワーク変数で処理するという事になると思います。

    NULL終端を探して暴走している場合、どんな結果になるのかは神のみぞ知るではないかと思いますけれど。
    CStringのコードを一々最後まで追いかければどうなっているかわかるかもしれませんけれど、
    そこまでするまでもなく、まずいと思います。


    解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。
    • 回答としてマーク 山本春海 2011年4月4日 8:12
    2011年3月14日 9:27
  • 質問文をよく読むとわかりますが、終端の'\0'のための領域がもともと存在しません。

    それと質問者は「キャスト(特にreinterpret_cast的な意味で)」や「足し算」を行っただけで「コンストラクタ呼び出し」や「オブジェクト生成」を行っている意識がないのだと思います。

    それからわざわざNUL終端せずとも読み込む文字列の最大長をあらかじめ指定しておけば安全です。(私の挙げたコードはそうなっています。)

    2011年3月14日 9:41
  • 質問文をよく読むとわかりますが、終端の'\0'のための領域がもともと存在しません。

    それと質問者は「キャスト(特にreinterpret_cast的な意味で)」や「足し算」を行っただけで「コンストラクタ呼び出し」や「オブジェクト生成」を行っている意識がないのだと思います。

    それからわざわざNUL終端せずとも読み込む文字列の最大長をあらかじめ指定しておけば安全です。(私の挙げたコードはそうなっています。)

    NULL終端の話は最初から既に上がっていますからねぇ。

    すいません、書式指定文字列で %.4sとした時は対象のデータのNULL終端は必要ないんでしたっけ?
    私はNULL終端必須と言う意識だったので必ず着ける様にしていました。
    まあ、安全と解っていても念の為にやってしまいそうです、私の場合。


    解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。
    2011年3月14日 9:52
  • すいません、書式指定文字列で %.4sとした時は対象のデータのNULL終端は必要ないんでしたっけ?
    私はNULL終端必須と言う意識だったので必ず着ける様にしていました。
    まあ、安全と解っていても念の為にやってしまいそうです、私の場合。


    私も %.4s の部分にドキッとしたので、printf の書式指定のヘルプを見直してみました。

     %[flags] [width] [.precision] [{h | l | ll | I | I32 | I64}]type

     printf 関数で使用する場合は 1 バイト文字列、wprintf 関数で使用する場合はワイド文字列を指定します。最初の NULL 文字まで、または precision で指定した範囲内で文字が出力されます。

    ということなので、大丈夫なようですね。
    これを踏まえて 佐祐理さん のコードをよく見ると、「CStringA」になっていて、きめが細かいなと感じました。

    とはいえ、私がやるとしても安全第一でコーディングすると思います、多分。
    • 編集済み totojo 2011年3月16日 1:54 呼び捨てはダメです。
    2011年3月14日 10:08
  • CString str;
    str = ((CString)xxx001.aaa).Mid(0,4) + _T("-") + ((CString)xxx001.aaa).Mid(4,4) + _T("-") + ((CString)xxx001.aaa).Mid(8,4);

    これだけの処理でCStringオブジェクトインスタンスはいくつ作成されているかは理解されていますでしょうか?

    数え間違えていなければ8個作成されます。

    CString str;  // これもコンストラクタ呼び出しになる
    Cstring t1( xxx001.aaa );  // SHIFT_JIS → Unicodeへの文字コード変換を含む
    t1.Mid( 0, 4 );
    CString t2;
    Concatinate( t2, &t1[0], t1.GetLength(), &_T("-")[0], _tcslen( _T("-") ) );
    CString t3( xxx001.aaa );  // SHIFT_JIS → Unicodeへの文字コード変換を含む
    t3.Mid( 4, 4 );
    CString t4;
    Concatinate( t4, &t2[0], t2.GetLength(), &t3[0], t3.GetLength() );
    CString t5;
    Concatinate( t5, &t4[0], t4.GetLength(), &_T("-")[0], _tcslen( _T("-") ) );
    CString t6( xxx001.aaa );  // SHIFT_JIS → Unicodeへの文字コード変換を含む
    t6.Mid( 8, 4 );
    CString t7;
    Concatinate( t7, &t5[0], t5.GetLength(), &t6[0], t6.GetLength() );
    str = t7;

    内部的にはこんな処理になっています。

    2011年3月14日 11:50
  • なんで呼び捨てにされるのかなぁ…。

    最長でも4文字しか読み込まない指定なわけなので、NUL終端は必須ではない、と考えています。指定以上の範囲を読み込むということは、すなわちバッファオーバーランでありセキュリティホールの要因ですし。

    %sでなく%Sを使えばcharをwchar_tには変換できますが、char / wchar_tをTCHARに変換する型フィールド文字はないので難しいんですよね。プリプロセッサと組み合わせればやり過ごすことはできますが。

    2011年3月16日 1:52
  • なんで呼び捨てにされるのかなぁ…。


    こめんなさい。速攻で直しました。
    2011年3月16日 1:56
  • コンストラクタが裏で呼ばれてしまう件に関してはC++言語を使う以上は意識する必要ありですね。
    PC上で動かす場合は有り余るマシンパワーで何とかなってしまうケースも有りそうですけれど、
    組み込み系の場合はPCに比べるとCPUも弱いですからなるべく無駄な動きはしない方が良いですね。

    特にインスタンスの生成はオーバーヘッドが大きいでしょうから意識しておかないと
    なんでこれだけの処理なのにこんなに遅いんだろうと言う話になりそうです。

    C++言語を使う場合、こういった一時的なインスタンスが生成されてしまうケースと代入演算子の
    オーバーライドについて気をつけておいた方が良いと思います。
    内部に大きな配列を抱えているクラスの代入演算子に関してはよくよく考えて実装しておかないと
    パフォーマンスがガタ落ちになるケースがあります。
    以前にこれをやらかしてPC上で動かしていたにも関わらずあまりの遅さに閉口した事があります。

     


    解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。
    2011年3月16日 2:10
  • あんまり褒められたコードでないのは確かですが、
    「キャストの部分」の潜在的問題が、本件の原因では無い様に思います。
    おそらくコードが記載されていない

    >// 構造体xxx001にデータをセットする処理
    >  ・・・

    の前後に原因があるのではないでしょうか。おそらく実際の
    コードと記載されているコードが異なるのでしょう。
    何らかの原因で、XXX::aaa[0] 等に0x00が書かれてしまっている事が疑われます。

    2011年3月16日 2:28
  • あんまり褒められたコードでないのは確かですが、
    「キャストの部分」の潜在的問題が、本件の原因では無い様に思います。
    おそらくコードが記載されていない

    >// 構造体xxx001にデータをセットする処理
    >  ・・・

    の前後に原因があるのではないでしょうか。おそらく実際の
    コードと記載されているコードが異なるのでしょう。
    何らかの原因で、XXX::aaa[0] 等に0x00が書かれてしまっている事が疑われます。

    CStringのXCHAR*を一つだけ受け取るコンストラクタの場合、引き渡される文字列はNULL終端が期待されていると思うので
    問題あると思うのですが、違うのでしょうか。
    EVC++3.0でうまく動いているのはスタック上のどこかにある'\0'をみつけてたまたまうまく行っているだけなのではと思うのです。
    確かに構造体の各文字列がNULL終端されていれば問題ないかもしれません。

    追伸: 失礼、指摘されている部分を読み違えました。
    文字列が出てこない件に関して直接の原因はそれではないのではと言われていたのですね。
    確かに構造体にデータをセットしている部分で壊している可能性もあるかもしれません。
    (提示されている範囲のソースではわかりませんけれど)


    解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。
    • 編集済み PATIO 2011年3月16日 2:58
    2011年3月16日 2:47
  • CStringのXCHAR*を一つだけ受け取るコンストラクタの場合、引き渡される文字列はNULL終端が期待されていると思うので
    問題あると思うのですが、違うのでしょうか。

    同感です。
    構造体の実体がローカル変数で定義されているので、スタックのよろしくないエリアまで見に行く可能性があるのではないかと。
    CString のコンストラクタに有効な文字列を渡せていないので、CString が空っぽの文字列に置き換えたのではないでしょうか。
    2011年3月16日 2:56
  • 念のため。XCHAR*ではなくYCHAR*(PCYSTR)です。YCHAR*を受け取る場合には文字コード変換が必要になります。

    それから運よくNUL終端文字が見つかればいいですが、最悪の場合、際限なく文字列として読み込み、未割当ページに踏み込めば、アクセス違反で落ちます。そうでなくても意図しないデータを文字コード変換させるので、変換エラーも引き起こしかねません。

    「本件の原因では無い」には同意しますが、「褒められたコードでない」程度では済まず、書いてはいけないコードだと思います。

    2011年3月16日 4:04
  • 舌足らずですみません。スレ主さんの質問

    >キャストの仕方に何か問題があるのでしょうか?

    に対しては、当然問題ありのコードで、つっこみどころがいっぱいです。異論はありません。
    さて、問題の解決には、当該の「キャスト」部分を(分解)整理してみた上でないと何とも言えないのですが、

    >失敗時は「--」とだけ表示されます。
    >また、失敗した場合でも xxx001にデータをセットする部分では、正しくデータがセットされていることも確認済みです。

    に対しては、「その認識が誤っている可能性もあります」という見解です。
    誤解された方にお詫び申し上げます。

    2011年3月16日 4:33
  • 念のため。XCHAR*ではなくYCHAR*(PCYSTR)です。YCHAR*を受け取る場合には文字コード変換が必要になります。

    すいません、確認が不十分でした。


    内容的には最初の質問からは方向が変わっているとは思いますが、
    内容的には有意義な内容になっていると思います。
    キャストの部分でコンストラクタが動いてしまっている等の話も出てきていますし。
    そろそろ質問者ご本人にご登場願いたいところなんですが、いかがでしょう。


    解決した時は、参考になったレスポンスの所にある[回答としてマーク]ボタンをクリックしてスレッドを締めましょう。
    2011年3月17日 0:58