none
VC6からVS2005 C++への変換 RRS feed

  • 質問

  • VC++6からVS2005 C++への変換したところ、

    CStdioFileのOpenを呼んだところでAssert(アクセス違反)が発生してしまいます。(Filecore.cpp L:144)

    なにか、MFCの変換で注意する点とかあるのでしょうか?

    プロジェックトでMultiByteモードに設定変更はしました。

    CStdioFile m_file;

    CFileException e;

     m_file.Open(lpszPathName, CFile::modeRead | CFile::typeText),&e);
     

     

    2007年3月6日 7:11

すべての返信

  •  たぬきねいり さんからの引用

    CStdioFileのOpenを呼んだところでAssert(アクセス違反)が発生してしまいます。(Filecore.cpp L:144)

    Filecore.cpp の 144行目は

    // shouldn't open an already open file (it will leak)
    ASSERT(m_hFile == INVALID_HANDLE_VALUE);

    ですね。これから察するに、m_file がすでに Open されていて、再度 Open しようとすると、
    この ASSERT が発生します。

    例えば、

    CStdioFile m_file;

    CFileException e;
    m_file.Open(lpszPathName, CFile::modeRead | CFile::typeText, &e);
    m_file.Open(lpszPathName, CFile::modeRead | CFile::typeText, &e);

    を実行すると、2回目の Open で ASSERT します。

    Open を2回呼び出していないか、確認してみてください。

    また、以下のように CStdioFile のコンストラクタでファイルを指定していたりしても同様です。

    CStdioFile m_file(lpszPathName, CFile::modeRead | CFile::typeText);

    CFileException e;
    m_file.Open(lpszPathName, CFile::modeRead | CFile::typeText, &e);

    2007年3月7日 5:19
  • どうも回答ありがとうございました。

    別の場所で、sscanf関数を実行しているところがあって、これをやめてCStringを使うように

    なおしたら、なおりました。

    なぜ、CStdioFileのOpenでエラーが出るのかはよくわかりませんが。

     

    2007年3月8日 5:00
  • ちゃんとおかしくなった原因を突き止めないと本当に直ったかどうか分からないような気もしますが。
    sscanfを使っている一連の部分を修正した事で本当に大元の原因が取り除かれたのかどうか
    それが問題ですね。
    単にバグは残っていて見えなくなっているだけだとしたらかえって厄介です。

    2007年3月8日 5:22
  • sscanfからどうやってCStringにしたんだろうか?

    sscanfを消したら動くようになったということは、
    そこで不正なメモリアクセスによってメモリをつぶしてしまっていた可能性が大ですね。
    2007年3月8日 5:31
  • sscanf->Cstringの変換はは以下のようです

    VC6のときはsscanfをsscanf_sに直しました。 

    //line(CString) = "F000 :0000 0001 0002 0003 0004 0005 0006 0007"

      // 変更前
      unsigned short saMusic,addr;
      sscanf_s( line, "%x :%x %x %x %x %x %x %x %x", &addr,&sa[0],&sa[1],&sa[2],&sa[3],&sa[4],&sa[5],&saDevil,&sa[7] );

      // 変更後

      unsigned short saMusic,addr,j;
      CString sad;
      CString sdMusic;

      sad = line.Left(4);
      addr = Xfer(sad);   // Xfer:16進文字列を数値へ変換する関数

      for( j = 0 ; j < 8 ; j++ ){
       sd[j] = line.Mid(6+j*5,4);
       sa[j] = Xfer(sd[j]); // Xfer:16進文字列を数値へ変換する関数
      }
    // 16進文字列の数値への変換
    unsigned int Xfer(CString hexstr)
    {
     hexstr.TrimRight();
     int n = hexstr.GetLength();
     unsigned int add = 0;
     unsigned int csa;
     unsigned char cx;
     for( int i = 0 ; i < n ; i++ ){
      add *= 16;
      cx = hexstr.GetAt(i);
      if( cx >= 'A' && cx <= 'Z' ) csa = cx - 'A' + 0xA;
      else if( cx >= 'a' && cx <= 'z' ) csa = cx - 'a' + 0xA;
      else if( cx >= '0' && cx <= '9' ) csa = cx - '0';
      else csa = 0;
      add += csa;
     }
     return add;
    }

    2007年3月9日 4:29
  • やはりsscanf_sの書式指定文字列が間違っていますね。

    short型の値を取得するときは、

    "%x"

    ではなく

    "%hx"

    としなければなりません。

    [MSDN]scanf 関数の文字幅指定 
    2007年3月9日 4:36
  • ちなみに、16進文字列→数値の変換関数ならば
    strtol,stroulとかがあります。
    (CStringならば、TCHAR用の、_tcstol,_tcstoul)
    2007年3月9日 4:43
  • "%hx"は全然知りませんでした

    >>strtol,stroulとかがあります

    >>(CStringならば、TCHAR用の、_tcstol,_tcstoul)

    今後はそうします。

    どうもありがとうございました

     

    2007年3月12日 1:21