動的な構造体の確保と解放方法について

このQ&Aのポイント
  • 構造体を動的に確保し、処理後メモリーリークが起こらない方法について説明します。
  • 質問のソースコードには、構造体の動的確保と解放の処理が含まれています。
  • 実行時にエラーが発生している原因についても解説します。
回答を見る
  • ベストアンサー

構造体を動的に確保&解放

度々お世話になってます。 構造体を動的に確保し、処理後メモリーリークが起こらないように解放したいです。 item を m_xcList.GetItemCount() 個、宣言したいです。 ご教授願いたいです。 ▼ソースの一部抜粋▼ void CFileListCreatorDlg::SameItemCheck(CString mySwitch) {  LVITEM  lvi;  int   index = 0;  UpdateData();  lvi.mask = LVIF_TEXT;  CString FullPathString;  CString myFileName;  index = 0;  while (index < CFileListCreatorDlg::m_xcList.GetItemCount()){   lvi.iItem = index;   lvi.iSubItem = 0;      lvi.pszText = const_cast<LPTSTR>(static_cast<LPCTSTR>(_T("")));   CFileListCreatorDlg::m_xcList.SetItem(&lvi);   index++;  }  //0:ファイル重複識別ナンバー 1:通し番号 2:フルパス 3:ファイル名 4:おおよそのデータサイズ 5:データサイズ 6:修正日 7:修正時間 8:備考欄 9:書式情報  //ファイル名、ファイル容量、修正日時により、重複チェック  struct item  {   CString RepetitionNum; //ファイル重複識別ナンバー   //int  Num;  //通し番号   CString FullPath; //ファイルパス   CString FileName; //ファイル名   //CString ApproximateByte; //おおよそのデータサイズ//バイト   CString AccurateByte;  //実際のデータサイズ//実バイト      //TCHAR ModifyDate[20];  //修正日   //CTime ModifyTime;  //修正時間      CString ModifyTime;  //修正時間      //TCHAR RemarksColumn[100];  //備考欄  };  //http://www-watt.mech.eng.osaka-u.ac.jp/~tasai/cp/lec1.html ← プログラム5を参考にしました。  struct item *array;  /* メモリの確保 */  array = (struct item*)malloc(sizeof(struct item)*(CFileListCreatorDlg::m_xcList.GetItemCount()-1));  if (array == NULL) {   StatusStringSet(_T("memory allocation error\r\n"),0,TRUE);   exit(EXIT_FAILURE);  }  //const int itemNum = sizeof item /sizeof array[0];  int i;  for (i = 0; i < CFileListCreatorDlg::m_xcList.GetItemCount(); i++) //初期化  {   array[i].RepetitionNum = _T(""); //ファイル重複識別ナンバー   array[i].FileName = _T(""); //ファイル名   array[i].AccurateByte = _T(""); //データサイズ   array[i].ModifyTime = _T(""); //修正時間  } int cc;  int dd;  cc = 1;  dd = 1;  if(mySwitch == _T("SameItemCheck_BY_FileName")){   //0:ファイル重複識別ナンバー 1:通し番号 2:フルパス 3:ファイル名 4:おおよそのデータサイズ 5:データサイズ 6:修正日 7:修正時間 8:備考欄 9:書式情報   StatusStringSet(_T("ファイル名により、重複チェック"),0,FALSE);   index = 0;   while (index < CFileListCreatorDlg::m_xcList.GetItemCount()){    array[index].RepetitionNum = _T("");    FullPathString = CFileListCreatorDlg::m_xcList.GetItemText(index,2);    if(FullPathString != _T("")){     array[index].FileName = FullPathToFileName(FullPathString);    }    for (dd = 0; dd <= index-1; dd++){     if (array[dd].FileName == array[index].FileName){      if (array[index].RepetitionNum != _T("")){       array[dd].RepetitionNum = array[index].RepetitionNum;       //" 重複番号欄に既に重複Noが、入っているとき"      }else{       //cc // " インクリメントcc"        CString str;        if (cc>=INT_MAX){         str = _T("MAX-Value");        }else{         str.Format(_T("%d"),cc);        }        array[index].RepetitionNum = const_cast<LPTSTR>(static_cast<LPCTSTR>(str));        if (array[dd].RepetitionNum != array[index].RepetitionNum){         cc++;        }      }      lvi.iItem = index;      lvi.iSubItem = 0;         lvi.pszText = const_cast<LPTSTR>(static_cast<LPCTSTR>(array[index].RepetitionNum));      CFileListCreatorDlg::m_xcList.SetItem(&lvi);      UpdateData(FALSE);            lvi.iItem = dd;      lvi.iSubItem = 0;         lvi.pszText = const_cast<LPTSTR>(static_cast<LPCTSTR>(array[index].RepetitionNum));      CFileListCreatorDlg::m_xcList.SetItem(&lvi);      UpdateData(FALSE);     }    }    index++;    UpdateData(FALSE);   }  }else if(mySwitch == _T("SameItemCheck_By_DataSize")){   //省略  } } ▲ソースの一部抜粋▲ コンパイルは通るのですが、実行時に↓のエラーがでます。 どこの部分ががおかしいのでしょうか??  ▼エラーメッセージ▼  FileListCreator.exe の 0x00f08ac1 でハンドルされていない例外が発生しました: 0xC0000005: 場所 0xcdcdcdbd を読み込み中にアクセス違反が発生しました。  void Empty() throw()  {   CStringData* pOldData = GetData();   IAtlStringMgr* pStringMgr = pOldData->pStringMgr;   if( pOldData->nDataLength == 0 )   {    return;   }   if( pOldData->IsLocked() )   {    // Don't reallocate a locked buffer that's shrinking    SetLength( 0 );   }   else   {    pOldData->Release();    CStringData* pNewData = pStringMgr->GetNilString();    Attach( pNewData );   }  }  ▲エラーメッセージ▲ 汎用的なコードをお教え願いたいです。宜しくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

#include <stdio.h> int main() { int a[5]; for (i=1; i<=5; ++i) a[i] = i*i; for (i=1; i<=5; ++i) printf("a[%d]=%d\n", i, a[i]); return 0; } というプログラムは間違っています. どこが間違いかわかりますか?

psychang
質問者

お礼

肝心の宣言部が抜けていました。お礼欄にて失礼いたします。  struct itemStruct  {   CString RepetitionNum; //ファイル重複識別ナンバー   CString FullPath; //ファイルパス   CString FileName; //ファイル名   CString AccurateByte;  //実際のデータサイズ//実バイト   CString ModifyTime;  //修正時間  };  itemStruct *item;  item = new itemStruct[CFileListCreatorDlg::m_xcList.GetItemCount()]; それと、一応、処理部の外でもリストコントールの重複ナンバー欄を初期化しています。 冗長かもしれませんが。  LVITEM  lvi;  int   index = 0;  UpdateData();  lvi.mask = LVIF_TEXT;  CString FullPathString;  index = 0;  while (index < CFileListCreatorDlg::m_xcList.GetItemCount()){   lvi.iItem = index;   lvi.iSubItem = 0; //重複ナンバーが入るコラム   lvi.pszText = const_cast<LPTSTR>(static_cast<LPCTSTR>(_T("")));   CFileListCreatorDlg::m_xcList.SetItem(&lvi);   index++;  } 以上です。

psychang
質問者

補足

遅くなりました。 【誤】i<=5 【正】i<5 new とか、配列の宣言方法に目を囚われて、すみません。添え字の問題でしたか。 今、動作確認をしました。大丈夫そうです。 同様に、自プログラムの初期化部分と処理部分の終了条件を一つ少なくして、表記をそろえました。 【誤】i <= CFileListCreatorDlg::m_xcList.GetItemCount() 【正】i < CFileListCreatorDlg::m_xcList.GetItemCount() void CFileListCreatorDlg::SameItemCheck(CString mySwitch) {  ▼初期化▼  int i;  for (i = 0; i < CFileListCreatorDlg::m_xcList.GetItemCount(); i++) //初期化  {   item[i].RepetitionNum = _T(""); //ファイル重複識別ナンバー   item[i].FileName = _T(""); //ファイル名   item[i].AccurateByte = _T(""); //データサイズ   item[i].ModifyTime = _T(""); //修正時間  }  ▲初期化▲  ▼重複ファイルチェック部分▼ cc = 1;  if(mySwitch == _T("SameItemCheck_BY_FileName")){ //m_xcListのコラムの添え字↓   //0:ファイル重複識別ナンバー 1:通し番号 2:フルパス 3:ファイル名 4:おおよそのデータサイズ 5:データサイズ 6:修正日 7:修正時間 8:備考欄 9:書式情報   //ファイル名により、重複チェック   index = 0;   while (index < CFileListCreatorDlg::m_xcList.GetItemCount()){    FullPathString = CFileListCreatorDlg::m_xcList.GetItemText(index,2);    if(FullPathString != _T("")){     item[index].FileName = FullPathToFileName(FullPathString); //ファイル名を取得するユーザー関数    }    for (dd = 0; dd < index; dd++){     if (item[dd].FileName == item[index].FileName){      if (item[index].RepetitionNum != _T("")){       item[dd].RepetitionNum = item[index].RepetitionNum;       //" 重複番号欄に既に重複Noが、入っているとき"      }else{       //cc // " インクリメントcc"        CString str;        if (cc>=INT_MAX){         str = _T("MAX-Value");        }else{         str.Format(_T("%d"),cc);        }        item[index].RepetitionNum = const_cast<LPTSTR>(static_cast<LPCTSTR>(str));        if (item[dd].RepetitionNum != item[index].RepetitionNum){         cc++;        }      }      lvi.iItem = index;      lvi.iSubItem = 0;         lvi.pszText = const_cast<LPTSTR>(static_cast<LPCTSTR>(item[index].RepetitionNum));      CFileListCreatorDlg::m_xcList.SetItem(&lvi);      UpdateData(FALSE);            lvi.iItem = dd;      lvi.iSubItem = 0;         lvi.pszText = const_cast<LPTSTR>(static_cast<LPCTSTR>(item[index].RepetitionNum)); // item[dd] ではなく item[index]の重複ナンバーを代入      CFileListCreatorDlg::m_xcList.SetItem(&lvi);      UpdateData(FALSE);     }    }    index++;   }  ▲重複ファイルチェック部分▲  delete [] item; } //SameItemCheck 終端 これでも、最初の目的であるメモリーリークが防げないようでしたら、お教え下さい。 明日あたりに、締め切ります。ありがとうございました。

その他の回答 (3)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

あとついでですが C でキャストしなくていいというのは 20年以上昔からそうですし, C++ なら std::vector 使えばいいような.

psychang
質問者

補足

アドバイスありがとうございます。 でも、今回のところは、new/deleteを採用したいです。 今のところ、↓ですが、どこが悪いのか分かりません。。。 {  struct itemStruct  {   CString RepetitionNum; //ファイル重複識別ナンバー   CString FullPath; //ファイルパス   CString FileName; //ファイル名   CString AccurateByte;  //実際のデータサイズ//実バイト   CString ModifyTime;  //修正時間  //} item[] =  // {_T(""),_T(""),_T(""),_T(""),_T(""),  };  itemStruct *item;  item = new itemStruct[CFileListCreatorDlg::m_xcList.GetItemCount()];  int i;  for (i = 1; i <= CFileListCreatorDlg::m_xcList.GetItemCount(); i++) //初期化  {   item[i].RepetitionNum = _T(""); //ファイル重複識別ナンバー   item[i].FileName = _T(""); //ファイル名   item[i].AccurateByte = _T(""); //データサイズ   item[i].ModifyTime = _T(""); //修正時間  }  ~処理~  delete [] item; } 以上、プログラム抜粋は、実行時エラーで、  void Empty() throw()  {   CStringData* pOldData = GetData();   IAtlStringMgr* pStringMgr = pOldData->pStringMgr; //←ここで止まってしまいます。   if( pOldData->nDataLength == 0 )   {    return;   }   if( pOldData->IsLocked() )   {    // Don't reallocate a locked buffer that's shrinking    SetLength( 0 );   }   else   {    pOldData->Release();    CStringData* pNewData = pStringMgr->GetNilString();    Attach( pNewData );   }  } どうかお教え下さい。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

「リストの行数分使う」のに「リストの行数分 - 1」だけ確保すれば十分である, という認識ですか?

psychang
質問者

補足

ごめんなさい、「リストの行数分使う」のに「リストの行数分 - 1」で良いという意味ではなく、私の間違って書いたコードが「リストの行数分 - 1」であって、要修正であるという意味です。「リストの行数」から「-1」しないように、「index<リストの行数」にしないように訂正しなきゃ駄目ですね。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

他にもあるかもしれませんが、とりあえず > array = (struct item*)malloc(sizeof(struct item)*(CFileListCreatorDlg::m_xcList.GetItemCount()-1)); これでstruct itemが何個分、確保できたと思いますか? > for (i = 0; i < CFileListCreatorDlg::m_xcList.GetItemCount(); i++) //初期化 これで、何個分、struct itemを使うと思いますか? それから、mallocに対してのfreeが無いようです。省略したところにあるかもしれませんが。 あとは、C++として使ってますよね?いろいろCには無い機能とか使われてますし。 それなら、malloc/freeよりはnew/delete を使った方がいいと思います。 まず、sizeofを使った計算も、ポインタのキャストも必要ありません。(最近のCならvoid*からキャストする必要は無いですが、C++だと必要) コンストラクタ/デストラクタを丁寧に書いて、メンバの領域確保/解放を確実にするのもメモリリーク対策の一つですが、malloc/freeではコンストラクタ/デストラクタは呼ばれません。

psychang
質問者

お礼

目的の機能ができました。malloc/free にしようとしていましたが、new/delete を教えていただきありがとうございます。 Vistaや7では、ちゃんと描画されるのに、XPでは描画されなかったので、 RedrawWindow(); //追加2011.12.10 //XP対策:再描画 をユーザー関数の最後にいれました。 それでは、またお世話になるかもしれませんが、そのときは宜しくお願いいたします。 (締め切ります。ポイントを差し上げられなくてごめんなさい。)

psychang
質問者

補足

さっそくのご回答ありがとうございます。お礼が遅くなってすみません。 > > array = (struct item*)malloc(sizeof(struct item)*(CFileListCreatorDlg::m_xcList.GetItemCount()-1)); > これでstruct itemが何個分、確保できたと思いますか? 構造体を使うのは初めてで、何で型変換やサイズを取るのか、理解はしてませんが、 間違っているのですね。。。リストの行数分 - 1ですね。 でも他が悪いのか、試してみましたが、駄目でした。 > > for (i = 0; i < CFileListCreatorDlg::m_xcList.GetItemCount(); i++) //初期化 > これで、何個分、struct itemを使うと思いますか? これは行数分使うと思います。 > それから、mallocに対してのfreeが無いようです。省略したところにあるかもしれませんが。 すみません、投稿するときに削ってしまいましたm(_ _)m > それなら、malloc/freeよりはnew/delete を使った方がいいと思います。 > まず、sizeofを使った計算も、ポインタのキャストも必要ありません。(最近のCならvoid*からキャストする必要は無いですが、C++だと必要) > コンストラクタ/デストラクタを丁寧に書いて、メンバの領域確保/解放を確実にするのもメモリリーク対策の一つですが、malloc/freeではコンストラクタ/デストラクタは呼ばれません。 調べてみました、確かにnew/deleteの方が良いようですね。ありがとうございます。 でも、malloc/freeを使った例も知りたいですが… new/deleteで試みてますが、苦戦中です。 new の宣言部がわかりません・・・ ◆開発環境 色々と環境や言語を書いてなくてすみません。 VC++2010、MFC、ユニコードを使用する設定になっています。 XP~7に対応させたいです。関係あるかは分かりませんが、スタティックリンク・マルチスレッドの設定です。

関連するQ&A

  • フォルダ内検索

    VC++6.0のMFCで開発しています。 フォルダをどろっぷしてフォルダ内のファイルを取り出すという プログラムです。 メインダイアログのクラス for(int p=0;p<__argc-1;i++) { CFileFind find; CString vv; vv=__argv[p]; CString Newstr=vv+_T("\\*.*"); if(find.FindFile(Newstr)){ int i=1; while(i){ if(__argv[p]==""){ return 0; } i=find.FindNextFile(); if(find.IsDots()){ continue; } if(find.IsDirectory()){ FolderDrop(find.GetFilePath()); } CString filename=vv+"\\"+find.GetFileName(); CString kakucho=GetKaku(filename); while((index3=m_listC.GetNextItem(index3,LVNI_ALL))!=-1){ indexstr=m_listC.GetItemText(index3,0); if(kakucho==indexstr){ kdlg.m_DirectoryFileNameArray.Add(filename); } } m_FilenameArray.Add(filename); m_FolderFileNumber++; } find.Close(); } } void CDragDrop6Dlg::FolderDrop(CString str) { CString kakucho; int i=m_listC.GetItemCount(); CString indexstr; CString filename2; CKakuninDlg kdlg; int p; int index3=-1; for(p=0;p<=c;p++){//ドロップしたファイルがディレクトリの場合 CFileFind find; CString Newstr=str+_T("\\*.*"); if(find.FindFile(Newstr)){ int i=1; while(i){  i=find.FindNextFile(); if(find.IsDots()){ continue; } if(find.IsDirectory()){ FolderDrop(find.GetFilePath()); } filename2=str+"\\"+find.GetFileName(); kakucho=GetKaku(filename2)//ファイルの拡張子を取り出す while((index3=m_listC.GetNextItem(index3,LVNI_ALL))!=-1){ indexstr=m_listC.GetItemText(index3,0); if(kakucho==indexstr){ kdlg.m_DirectoryFileNameArray.Add(filename2); } } m_FilenameArray.Add(filename2); m_FolderFileNumber++; } find.Close(); } } としてフォルダAの中にフォルダBが入っていてその中に入っているファイルCを取り出したいのです。 このプログラムではドロップしたファイルが 一番目のプログラムでフォルダA内の中身がファイルならfilenameに フォルダならBに潜り込む所まではいけました。 しかし実際に別ダイアログに取り出した全てのファイルの一覧を出すと A内のプログラムしか表示されません。どこがいけないのでしょうか?

  • 動的に確保した配列のファイルへの書き出し

    動的に確保した配列を、ファイルに書きだそうとしています。 int i, arraysize = 10; int **array; array = new int*[ arraysize ]; for (i = 0 ; i < arraysize ; i++) array[ i ] = new int [ arraysize ]; ofstream out("filename", ios::out | ios::binary); out.write((char *) array, sizeof( array )); これでは array のポインタが書き込まれるだけ、なのかな ? ということで、配列を書き込む目的を果たせておりません。このように動的に確保した多次元配列 (要素数は既知) をファイルに書き込むためにはどうすればよろしいでしょうか。

  • CSting を TCHAR [] に変換したい。

    Visual Sutdio 2010 , VC++ , MFC でファイルリスト一覧作成ソフトを作っている者です。 CSting 型の _T("~\0~\0\0") を TCHAR [] に変換したいです。 CSting 型の変数名は、DeleteFilePathです。 '\0' を他の文字に置換して確認した所、正しく入っています。 現在は、4096文字の文字列配列に入れています。 ゴミ箱に移動できる時とできない時があります。 _______________________________________________________________________________ ■現在のコード  index = -1;  while ((index = CFileListCreatorDlg::m_xcList.GetNextItem  (index, LVNI_ALL | LVNI_SELECTED)) != -1)  {   CString FullPathString = CFileListCreatorDlg::m_xcList.GetItemText(index,2);   if (FullPathString.Right(1) != _T("\\")){     ::SetFocus(::GetDlgItem(m_hWnd,IDC_LIST));    FullPathString.Replace(_T ("\\"),_T("\\\\"));    DeleteFilePath = DeleteFilePath + FullPathString + _T('\0');    CFileListCreatorDlg::m_xcList.DeleteItem(index);   }   index--;  }  DeleteFilePath = DeleteFilePath + _T('\0');  _TCHAR cszPath[4096];   // TCHAR型  _tcscpy(cszPath, DeleteFilePath);  // CString型→TCHAR型  SHFILEOPSTRUCT sfs;  memset ( &sfs, 0, sizeof ( SHFILEOPSTRUCT ) );  sfs.fFlags = FOF_NOERRORUI | FOF_SIMPLEPROGRESS | FOF_ALLOWUNDO;// ゴミ箱へ移動の確認をする場合 FOF_ALLOWUNDO をつける;  sfs.wFunc = FO_DELETE;  sfs.pFrom = cszPath;  if ( 0 != SHFileOperation ( &sfs ) )  {   MessageBox(_T("ゴミ箱に移動できませんでした"),_T("SHFileOperation 失敗"),MB_OK);   return 0;  } _________________________________________________________________________________________________________________________________________________ 5回に1回成功するので、不思議です。 ファイルのパスは、リストコントロールのアイテムに格納されていて、 削除したいアイテムを選択肢、Shift + Delete で、ゴミ箱に削除する ユーザー関数が呼び出されます。(ゴミ箱に移動するだけで、確認メッセージは出なくていいです。) 今まで、具体的した事を記すと以下のようになります。 cszPath = const_cast<LPTSTR>(static_cast<LPCTSTR>DeleteFilePath;  //ビルドエラー としたり、 _TCHAR cszPath[DeleteFilePath.GetLength()];  // TCHAR型 としたり、 TCHAR cszPath[256];  // TCHAR型 _tcscpy(cszPath, DeleteFilePath);  // CString型→TCHAR型 ・・・とやってみましたが、出来ません。 http://www.usefullcode.net/2006/12/post_13.html http://www5d.biglobe.ne.jp/~noocyte/Programming/Windows/WindowsTips.html#MoveToRecycleBin とかが参考になりそうです。 先程も書きましたが const _TCHAR cszPath[] = _TEXT ( "C:\\a.txt\0C:\\b.txt\0" ); の代入がうまく行きません。 ____________________________________________________________________________________________________________________________________ http://sysneitf.ifdef.jp/shell_filestotrash.html 以下、参考にした部分 // 複数ある場合は、パスを'\0'で区切る。終端は、'\0''\0'である必要がある  const _TCHAR cszPath[] = _TEXT ( "C:\\a.txt\0C:\\b.txt\0" ); // "c:\\a.txt"と"C:\\b.txt" をゴミ箱へファイルを移動するサンプル (シェルエミュレート)  SHFILEOPSTRUCT sfs;  memset ( &sfs, 0, sizeof ( SHFILEOPSTRUCT ) );  sfs.fFlags = FOF_NOERRORUI | FOF_SIMPLEPROGRESS | FOF_ALLOWUNDO;// ゴミ箱へ移動の確認をする場合  FOF_ALLOWUNDO をつける;  sfs.wFunc = FO_DELETE;  sfs.pFrom = cszPath;  if ( 0 != SHFileOperation ( &sfs ) )  {   MessageBox ( NULL,   _TEXT ( "SHFileOperation 失敗" ),   _TEXT ( "エラー" ),   MB_OK | MB_ICONSTOP );  } どなたか、お教え下さると嬉しいですm(_ _)m

  • Debug Assertion Failed

    前回フォルダの中のフォルダの中のファイル検索について質問させていただきましたが再帰を使えというアドバイスをいただきVC++6.0のMFCダイアログベースにて 【InitDialog内】 if(int p=0; p<=argc;p++){ test(__argv[p]); } void ●Dlg::test(CString strFolder) { CFileFind find; CString Newstr=strFolder+_T("\\*.*"); if(find.FindFile(Newstr)) { int i=1; while(i) { if(strFolder==""){ return 0; } i=find.FindNextFile(); if(find.IsDots()){ continue; } if(find.IsDirectory()){ test(find.GetFilePath()); } CString filename=strFolder+"\\"+find.GetFileName(); m_Ary.Add(filename); find.close(); } } } ※m_Aryは●Dlgクラスのメンバ変数 CStringArray m_Ary; これを実行すると Debug Assertion Failedが出てきて デバッグを押すと BOOL CFileFind::FildNextFile() { →ASSERT(m_hContext !=NULL) →の所でひっかかってるようです。 どうすれば直りますか?

  • realloc の使い方について教えてください!

    http://okwave.jp/qa/q7445404.html で質問した者です。 【1】 あれから試行錯誤して、new と delete を使うことを試みました。まずOnInitDialog()で、サイズが0の 構造体を生成して、prevDataを毎回 delete してから、new してたのですが、UNDOは出来ましたが、REDOが できません。 【2】 ちなみに、前回質問時の m_xcList を(リストコントロールごと)退避して、一個前と 今回のリスト全体を置き換える方法は、outList->DeleteAllItems();の後、どうやっても 復元できないので、やめました。 【3】 今回の質問は、構造体をreallocで、その都度上書きしたい(する方針に変えました)です。 できればメモリーが足りない場合は、エラー処理もしたいと考えています。今は都合上、構造体要素は すべて、String型で定義しています。後で、TCHARに直します。 今の状態は、malloc_Func()が2度呼ばれると「ハンドルされていない例外が発生しました」と でて、止まります。構造体配列のサイズがうまく取れていないと思っています。 →prevData[ItemNo].RepetitionNum = inData; で止まります。  typedef struct any {   //int *i;   CString RepetitionNum; //ファイル重複識別ナンバー   CString Num;  //通し番号   CString FullPath; //ファイルパス   CString FileName; //ファイル名   CString ApproximateByte; //おおよそのデータサイズ//バイト   CString AccurateByte;  //実際のデータサイズ//実バイト   CString ModifyDate;  //修正日   CString ModifyTime;  //修正時間   CString RemarksColumn;  //備考欄   CString FormatDataStr; //書式情報   //item():   //~item();  }ListItemStruct;  ListItemStruct *prevData;  ListItemStruct *nowData;  ListItemStruct *workData; void malloc_Func(int ItemCount,CString targetName); //このユーザー関数内でreallocしています。  //以下の3つのグローバル変数は、最後の GetItemCount() で取得してINDEXを退避しています。  int LastPrevItemCount;  int LastNowItemCount;  int LastWorkItemCount;  //http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1117611511  //http://blogs.wankuma.com/jitta/archive/2008/12/16/164045.aspx //ユーザー関数内で、分岐して、各ポインターに合わせた処理を行うようになっています。 //一箇所に纏めたかっただけです。 void CFileListCreatorDlg::malloc_Func(int ItemCount,CString targetName){  if (targetName=_T("prevData")){   {    int ItemNo = 0;    int SubItemNo = 0;    int err = 0;    ItemNo = 0;     while ( ItemNo < ItemCount ) //ItemCount分、構造体配列をreallocします。     {          //if( ItemCount == 0 ) {//この↓部分はアプリ起動時一回目にしか実行されないようにOnInitDialog()に記述しました。      // prevData = (ListItemStruct*)malloc(sizeof(ListItemStruct));      // if (prevData == NULL) { return; }      //}else{       ListItemStruct* dummy = (ListItemStruct*)realloc(prevData,sizeof(ListItemStruct)*ItemNo+1);       if (dummy == NULL) {        if (prevData != NULL){         free(prevData);         prevData = NULL;        }       }else{        prevData = dummy;       }      //}      SubItemNo=0;      while (SubItemNo<=9){       //if (!err)       {        CString inData;        inData = CString(m_xcList.GetItemText(ItemNo, SubItemNo));              switch (SubItemNo){         case 0:          prevData[ItemNo].RepetitionNum = inData;          break;         case 1:          prevData[ItemNo].Num = inData;          break;         case 2:          prevData[ItemNo].FullPath = inData;          break;         case 3:          prevData[ItemNo].FileName = inData;          break;         case 4:          prevData[ItemNo].ApproximateByte = inData;          break;         case 5:          prevData[ItemNo].AccurateByte = inData;          break;         case 6:          prevData[ItemNo].ModifyDate = inData;          break;         case 7:          prevData[ItemNo].ModifyTime = inData;          break;         case 8:          prevData[ItemNo].RemarksColumn = inData;          break;         case 9:          prevData[ItemNo].FormatDataStr = inData;          break;        }              CFileListCreatorDlg::StatusStringSet(_T("UNDOデータ 退避中"),0,FALSE);//ダイアログ上のテキストに状態を記しています。       }       SubItemNo++;      }      ItemNo++;     }   } } プログラムが終わるときに解放しています。 free(prevData); prevData = NULL; free(nowData); nowData = NULL; free(workData); workData = NULL; 参考書も見てみたのですが、分かりません。まずは一応動く程度でも構いませんので、 教えてくださると嬉しいです。宜しくお願いします。

  • UpdateData( FALSE); による文字列データの表示更新(VC++6.0)

    VC++の超初心者です. UpdateData( FALSE ); を用いてエディットボックスの文字列の表示の更新を 試みているのですが,たとえば,以下のコードのようにボタンをクリックした際に文字列表示の更新を複数回行おうとするとうまくいきません. 具体的には一回目のUpdateData( FALSE );が反映されず二回目のUpdateData( FALSE );のみ反映されるという症状です. なおm_mojiretsuはCstring型でエディットボックスのDDX用の変数です. void CMyDlg::OnButton1() { DWORD p; m_mojiretsu=_T("mojirstu1"); UpdateData( FALSE ); /*5秒の待ち*/ p=timeGetTime(); while(1){if((timeGetTime()-p)>5000) break;} m_mojiretsu=_T("mojirstu1\r\nmojirstu2"); UpdateData( FALSE ); } 何か別の処理を行わなければいけないのでしょうか. どこかに根本的なミスがあるのでしょうか. VC歴3日程度で,右も左も分からず大変困っております.よろしくお願いします.

  • フォルダ検索

    VC++6.0のMFCでプログラムを組んでいます。 CFileFind find; CString Newstr=●●+_T("\\*.*"); if(find.FindFile(Newstr)) { int i=1; while(i) { if(●●==""){ return 0; } i=find.FindNextFile(); if(find.IsDots()){ continue; } if(find.IsDirectory()){ continue; } CString filename=●●+"\\"+find.GetFileName(); } } とすると●●フォルダの中のファイル名がfilenameに取得されます。 しかしもしフォルダの中にフォルダがある場合その中身も取得したいのですがどうすればいいのかわかりません。フォルダの中にフォルダが無くなるまで調べつづける予定です。

  • templateをシリアライズするには?

    templateで作った変数をシリアライズする方法がわからなくて困っています。 例えばhogehogeという変数を用意します。これはtemplateで hogehoge<TYPE>として、型はint、double、char[]、wchar_t[] のいづれかを取れるようにします。 この変数hogehogeをシリアライズしてファイルに保存したいのです。 シリアライズするには、int又はCObject*又はCString型にいったん キャストしてからシリアライズすることになると思うのですが ここで、hogehogeという変数がどの型になっても問題なくシリアラ イズできるようにするにはどうしたらいいのでしょうか?

  • 解説お願いします。

    知り合いからソースをもらったtxtファイルのランダム取得なのですが どういう動きをしているのかさっぱりなので誰か解説をお願いします。 このソースをくれた人に聞けば早いのですが連絡が取れなくなってしまったので^^; //index側のソース //ランダム表示 $sorce_dir = './hide_pc/rand_index_top'; @include_once('./hide_pc/randam_k.php'); } //./hide_pc/randam_k.php側のソース <?php //$sorce_dir ソースの入ったディレクトリ mt_srand((int)(microtime() * 10000)); $rand_text = array(); $i = 1; if ($handlerDir = opendir($sorce_dir)){ while ($filename = readdir( $handlerDir )){ if ( $filename != "." && $filename != ".."){ array_push($rand_text,$filename); $i++; } } } $rand = mt_rand(0,(count($rand_text) - 1)); $randam_sorce = file_get_contents($sorce_dir.'/'.$rand_text[$rand]); ?> このソースを用意して./hide_pc/rand_index_topのディレクトリにtxtファイルをアップすれば<?=$randam_sorce ?>と指定したところに表示されます 解説よろしくお願いいたします。

    • ベストアンサー
    • PHP
  • template 参照 operator について

    「ゲームプログラマになる前に覚えておきたい技術」という書籍を読みながらC++でプログラミングの学習をしているのですが、template class と 参照 と operator の組み合わさったクラスでわからないところがあります。 自分で出来る限り調べてみましたが、解決できなかったので、答えていただけると幸いです。 Cの学習はひととおり済んでおりますが、まだC++は学習を始めたばかりなので理解が浅いです。 質問内容にいたらない点があるとは思いますが、お願いします。 以下のようなクラス定義文がありました。 template< class T > class Array2D{ public: Array2D() : mArray( 0 ){} ~Array2D(){ delete[] mArray; mArray = 0; } void setSize( int size0, int size1 ){ mSize0 = size0; mSize1 = size1; mArray = new T[ size0 * size1 ]; } T& operator()( int index0, int index1 ){ return mArray[ index1 * mSize0 + index0 ]; } const T& operator()( int index0, int index1 ) const { return mArray[ index1 * mSize0 + index0 ]; } private: T* mArray; int mSize0; int mSize1; }; この定義文の以下の部分 T& operator()( int index0, int index1 ){ return mArray[ index1 * mSize0 + index0 ]; } において、T&という記述がなければ、()という演算子のはたらきを再定義していて、 mArrayを2次元的に利用できるように値を返しているように見えるのですが、 T&がつくことによって、なにがどうなっているのでしょうか。 それと、参照というのは、利用するときには必ず初期化が必要、と学習したのですが、 この場合、初期化の処理になっているのでしょうか。 今までに出てきた参照では、簡単な例でいうと int n; int& m = n; というように、型名&別名=参照先 と、即初期化して使っていました。 これなら初期化されているのはわかりますが、今回のように、 「別名」の部分がoperatorになっていると、どのアドレスが「別名」が指すアドレスになるのでしょうか。 さっぱりわかりません。 質問の連続になってしまって申し訳ありません。 ほんとに困ってます。 おねがいします。

専門家に質問してみよう