クリップボードへのコピーに関するエラー解決方法

このQ&Aのポイント
  • あるHPのコードを参考に文字をクリップボードへコピーするコードを書いてみましたが、エラーが発生しています。
  • 特にヒープの壊れが原因と考えられます。ヒープを正しく扱う方法を確認しましょう。
  • コードに手抜きがあり、チェックが不十分ですが、一旦動作は正常とします。
回答を見る
  • ベストアンサー

クリップボードへのコピー

あるHPのコードを参考に文字をクリップボードへ コピーするコードを書いてみましたが、エラーが できます。なにかおかしいかご指摘いただけないでしょうか? HGLOBAL hText; wchar_t *pText; hText = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 4); pText = (wchar_t*)GlobalLock(hText); lstrcpy(pText, L"abc"); GlobalUnlock(hText); OpenClipboard(NULL); EmptyClipboard(); SetClipboardData(CF_TEXT, hText);//ここでヒープが壊れていると起こられます。 CloseClipboard(); もっとも単純なテストコードです。 いろいろとチェックを手抜きしてますが、とりあえずOKとします。

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

  • ベストアンサー
  • xcrOSgS2wY
  • ベストアンサー率50% (1006/1985)
回答No.1

GlobalAllocで割り当てサイズとして「4」を指定していますが、これは「4バイト」を意味します。 ところが、lstrcpyでコピーしているL"abc"は4文字=8バイトを占有するので、確保したメモリの量を超えてメモリを書き換え(=破壊)してしまっています。 これが原因ではないでしょうか。

milkoX
質問者

お礼

ご回答ありがとうございます。 いまちょうど自己解決したところです。 原因はおっしゃる通りです。 ただしくは hText = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 4 * sizeof(wchar_t)); です。 で、返信がない場合どうやって質問を締めようかと悩んでいたところです^^; #いつになったらこの文字操作に慣れてくるんだろう。。

関連するQ&A

  • クリップボードからJpgファイルへの保存方法(画質について)

    クリップボードにコピーされたデスクトップの画面を Jpgファイルに落とすプログラムです。 クリップボードから情報を取得してjpgファイルを作成することはできるのですが、画質が悪く (白黒のように)なってしまうのですが、なぜなのかわかりません。 アドバイスお願いします。 if (IsClipboardFormatAvailable(CF_DIB )) { ::OpenClipboard(NULL); HGLOBAL hGlobal; hGlobal = (HGLOBAL)::GetClipboardData(CF_DIB ); if( hGlobal == NULL ){ AfxMessageBox( "クリップボードへコピーできませんでした" ); return; } //ファイルに保存 ///////////////////// const CString szPptFilter = _T("PowerPoint Files (*.ppt)|*.ppt|"); CString szFilter = szPptFilter + _T("|"); CFileDialog dlg(FALSE, _T("ppt"), NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szPptFilter); if( dlg.DoModal() == IDOK ) { double lfProp = 1.0; TCHAR szTemp[_MAX_PATH]; BOOL bTemp = (GetTempPath(_MAX_PATH, szTemp) == 0)? FALSE:TRUE; CString szTempPath = bTemp? szTemp:_T("c:\\"); CString szFileName = szTempPath + _T("_") + "JpegFile" + _T(".jpg"); void *pDIB = GlobalLock( hGlobal ); CDib dib((BYTE*)pDIB); CPicObject::EPicKind eKind = CPicObject::GetKind(szFileName); if(eKind == CPicObject::eJpg) { CPicJpg pic(dib); //tmpフォルダに一時的に作成 bStatus = pic.Write(szFileName); }

  • c++ メモリの確保を動的に変更する

    VC++2008 Express版で以下のプログラム(第1引数をクリップボードにセット)を作成しましたがメモリの確保量を自動的に調節するようにしたいのですが、どうしたらよろしいですか #include <stdio.h> #include <windows.h> void main(int argc,char *argv[]) { OpenClipboard(NULL); int iStrLen = 8;//★ここを調整したい★ HGLOBAL hMem = ::GlobalAlloc(GMEM_FIXED, iStrLen); LPTSTR pMem = (LPTSTR)hMem; ::lstrcpy(pMem, (LPCTSTR)argv[1]); ::EmptyClipboard(); ::SetClipboardData(CF_TEXT, hMem); ::CloseClipboard(); }

  • 移動可能メモリ

    GlobalAlloc関数を調べていたんですが、GlobalLockしてメモリを固定するといっているのですが、その意味がピンときません。 GMEM_MOVEABLEで移動可能メモリの割り当てを行うようなんですが、 アドレスが移動するってどういうことなんでしょう? 固定メモリと移動可能メモリの違いってなんでしょうか?

  • CString データの文字数カウントができない

    VusualStudioのMFCでクリップボードのデータの文字数をカウントしようとしています。 Webにあったように以下のようなクラスを作成し、 =========================================================== CString CClipboard::GetClipboardText() { CString strText; strText.Empty(); // クリップボードにテキストデータが入っているかを調べる if( !::IsClipboardFormatAvailable(CF_UNICODETEXT) ) return strText; // クリップボードのオープン if( !::OpenClipboard(NULL) ) return strText; // クリップボードからデータを取得し、strTextへコピー HANDLE hMem = ::GetClipboardData(CF_UNICODETEXT); LPTSTR pMem = (LPTSTR)::GlobalLock(hMem); ::lstrcpy((LPTSTR)(LPCTSTR)strText, pMem); ::GlobalUnlock(hMem); ::CloseClipboard(); return strText; } =========================================================== 適当にメモ帳などでコピー操作をしたのち、 CClipboard board; CString a = board.GetClipboardText(); int b = a.GetLength(); 上記コードが含まれた操作を実行するとaという文字列自体はデバッガ上から"test"のように 認識されているのですが、bの値が0になってしまいます。 ちょっとわけがわからず途方に暮れています。 アドバイスがあればよろしくお願いします。

  • 【エクセルのマクロ】クリップボードのbitmapをフォームに表示させたい

    こんにちは! クリップボードにビットマップが入っていたとき、そのデータをフォームに表示させたりすることはできませんか?API関数にgetclipboarddata(cf_bitmap)というものがあり、これを使うことでデータは取得していると思うのですが、例えばImage1.Picture=GetClipBoardData(CF_BITMAP)というようにやっても〔オブジェクトが必要です〕というエラーが出てしまいます。 openclipboard(0)とかcloseclipboardとか、これらの宣言とか、概ね必要と思われるものはコードに組み込んであると思います。 正直申し上げて、完全な初心者です。どなたかお分かりになる方いらっしゃいますか? また、エクセルのグラフやシェイプをマクロを使い、bitmap形式で保存する方法はありませんか?VBの参考サイトで調べてみるとメタファイル形式で取得してやってらっしゃったのですが、エクセルのマクロではこれはできないでしょうか(自分が見たサイトではエクセルでサポートしていない関数を使っていました)? どなたか助けてください。よろしくお願いいたします。

  • メモリ違反でソフトが強制終了してしまいます。

    コンパイルして実行すると ttp://kei100.jp/diary/images/20050612_0.png このようなメッセージが表示されてしまいます。 #include <windows.h> #include <stdio.h> #include <string.h> void main(void) { HANDLE hFile; HGLOBAL hg = GlobalAlloc(GMEM_FIXED, 1000); char* test = "test"; LPTSTR aaa="spacetestspace"; char* bbb = NULL; char ccc[5]; aaa=(char*)GlobalLock(hg); bbb = strstr(aaa, test); strncpy(ccc, bbb, strlen(test)); printf("ccc = %s \n", ccc); GlobalUnlock(hg); GlobalFree(hg); GlobalFree(aaa); } どなたか解決方法を知っている方、回答よろしくお願いします。

  • htmlソースを一文字ずつ取得するには・・

    私は猫でもわかるネットワークプログラミングをよんでふと思ったのですが・ HTMLソースを空白行も含め縦に並べたいのです たとえば・・ < h t m l > ってな感じで・・ つまりは printf("%s(%cでも・・)",一文字); ってな感じにしたいのです・・ 一応作りかけのソース張っておきます。。。。 wininet使ってます・・ //省略 //インターネット(wininet)開始 hInet = InternetOpen("ユーザー名収集プロトタイプ",INTERNET_OPEN_TYPE_PRECONFIG, NULL,NULL,0); hUrl = InternetOpenUrl(hInet,szUrl,NULL,0,0,0); //lpszSrcに1バイトのみ確保 hMem = GlobalAlloc(GHND,1); lpszSrc = (char *)GlobalLock(hMem); //読み出すものがなくなるまで読み出す while(1){ InternetReadFile( hUrl,szBuf,(DWORD)sizeof(szBuf) - 1,&dwRead); szBuf[dwRead] = '\0'; //読み出すものが無くなったらループを脱出 if (dwRead == 0){ break; } //必要バイト数の計算 dwTotal += dwRead; //確保領域の大きさ変更 hMem = GlobalReAlloc(hMem,dwTotal,GMEM_MOVEABLE); if(hMem == NULL){ perror("再アロケート失敗\n"); } lpszSrc = (char *)GlobalLock(hMem); if(lpszSrc == NULL){ perror("メモリ領域確保に失敗\n"); break; } strcat(lpszSrc,szBuf); printf("%s\n",szBuf); } //メモリの開放 GlobalUnlock(hMem); GlobalFree(hMem); //インターネットハンドルの開放 InternetCloseHandle(hUrl); InternetCloseHandle(hInet); return 0; }

  • GlobalAlloc について

    GlobalAlloc について 質問させて下さい。 VC++ 2005 MFC で開発しております。 仕様の概要と致しまして、 ::GlobalAlloc()でHGLOBALを取得し、 メンバ変数に格納(Arrayでリサイクルしていくイメージ)した後、スレッドを走らせ格納したHGLOBALを 使い処理をした後に、GlobalFree()でメモリを開放します。 アプリの仕様上、スレッドの処理に少々時間がかかり GlobalAlloc()とGlobalFree()が必ずしも一対一で実行されず、 スレッドのGlobalFree()が実行される前に別のGlobalAlloc()がくることがあります。 このような場合、下記のように確保するヒープ領域の取得したアドレスが 少しずつ増えてしまい、最終的には取得できなく(GlobalLockでNULLポインタ)なってしまいます。(4GB越え) 8バイトずつアドレスが増えていくとして ------------------------------------------------- ・一対一の場合 (同じアドレスが使用できる) 確保 開放 (1)0008 (2)0008 (3)0008 (4)0008 (5)0008 ・一対一でない場合 (開放される前に確保するので新しいアドレスを使用してしまう) 確保 開放 (1)0008 (2)0008 (3)0008 (4)0016 (5)0008((3)メモリ) (6)0024 (7)0032 (8)0040 (9)0016((4)メモリ) (10)0024((6)メモリ) (11)0032((7)メモリ) (12)0048 : : : ------------------------------------------------- GlobalFree()がもれているのではなく メモリを確保したものは遅れはするものの必ず開放はしています。 このような場合、上記の「一対一でない場合」の (6)で「0024」番地ではなく「0008」番地からメモリを確保することは出来ないのでしょうか? 確保と開放が一対一に統合されていればこのような問題はない(常に同じアドレスを使用できるため)のですが、 アプリの使用上、仕方ないと考えております。 説明が複雑になってしまい、わかりにくいとは思いますが、 お詳しい方がおられましたら、ご教授の程宜しくお願い致します。

  • jpgファイルのダウンロード

    WWWサーバー上にあるjpgファイルを指定してそれをダウンロードするプログラムをつくっています。 jpgファイルが作成されることはされるのですが、中身をみることができない状態になってしまいます。 どこが悪いのかわかる方がおられましたらご教授お願いします。 <ソースコード> #include <windows.h> #include <stdio.h> #include <wininet.h> int main(void) { HINTERNET hInet, hUrl; char szBuf[128], szUrl[128], *lpszSrc; DWORD dwRead, dwTotal = 0; HGLOBAL hMem; FILE *file; printf("URL---- "); gets(szUrl); hInet = InternetOpen(TEXT("neko"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if(hInet == NULL){ perror("オープンエラー\n"); return -2; } hUrl = InternetOpenUrl(hInet, szUrl, NULL, 0, 0, 0); if(hUrl == NULL){ perror("URLオープンエラー\n"); return -3; } hMem = GlobalAlloc(GHND, 1); lpszSrc = (char*)GlobalLock(hMem); while(1){ InternetReadFile(hUrl, szBuf, (DWORD)sizeof(szBuf)-1, &dwRead); szBuf[dwRead] = '\0'; if(dwRead == 0){ break; } dwTotal += dwRead; hMem = GlobalReAlloc(hMem, dwTotal+1, GMEM_MOVEABLE); lpszSrc = (char*)GlobalLock(hMem); strcat(lpszSrc, szBuf); } if((file = fopen("test.jpg", "wb")) == NULL){ printf("ファイルオープンエラー\n"); goto end; } while(dwTotal){ fputc(*lpszSrc, file); lpszSrc++; dwTotal--; } fclose(file); end: GlobalUnlock(hMem); GlobalFree(hMem); InternetCloseHandle(hUrl); InternetCloseHandle(hInet); return 0; } <環境> Windows Vista VC++ 2005 EE

  • GDIによるメモリ上からの画像データ読み込みに関して

    開発環境はVC++/CLIです。 アンマネージ型のCOMオブジェクトの扱いで困っております。 JPEGやPNGなどの画像データを保存したunsigned char型配列から、Gdiplus::Bitmap型を作ろうとしています。 unsigned int imagesize; // 画像のバイト数が格納されている array<unsigned char>^ image = gcnew array<unsigned char>(imagesize); //画像のデータが格納されている 事前にこのようなデータを用意し、以下のように記述しました。 HGLOBAL hResourceBuffer = GlobalAlloc(GMEM_MOVEABLE , imagesize); void* pResourceBuffer = GlobalLock(hResourceBuffer); CopyMemory(pResourceBuffer, &image, imagesize); IStream* pIStream = NULL; CreateStreamOnHGlobal(hResourceBuffer, TRUE, &pIStream) data->bmp = new Gdiplus::Bitmap(pIStream); pIStream->Release(); GlobalUnlock(hResourceBuffer); GlobalFree(hResourceBuffer); しかしながら、上記のコードだと、CopyMemory時に「保護されたメモリに書き込もうとした」といったエラーが発生します。 Webで色々検索しましたが、全て似たような記述で動作していました。 何が問題なのでしょうか? 尚、上記と同様の画像データ配列を使って、System::Drawing::Bitmap型に格納したとき、画像が正常に表示されることを確認しております。 画像のバイト数に於いても取得したデータに間違いはなく、やはりメモリ関連の問題だと思うのですが…。 MemoryStream^ memst = gcnew MemoryStream(image); Bitmap^ bmp = gcnew Bitmap(memst); memst->Close(); Graphics^ im = pictureBox1->CreateGraphics(); im->DrawImage(bmp, 0, 0, 100, 100); delete bmp;

専門家に質問してみよう