質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.80%

ファイルマッピングについて

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 234

tmykbys

score 14

猫でもわかるC言語を履修中なのですが、
http://www.kumei.ne.jp/c_lang/intro2/no_114.htm
こちらのページの最下、サンプルプログラムをタグに示した環境でコピー・実行したところ、
l buffer is too small && 0
等のエラーが発生しました。

バッファが少なすぎるとのことなので増やしてみたりと試行錯誤を繰り返したのですが、
lpStr=NULLになったりととても初心者には分かりませんでした。

VisualStudioは最新版を使っており筆者様の環境と違って、セキュリティ的な面で様々な制約が発生しているからではないかと推測するのですが、どうすれば動くようになるのか教えていただけたら幸いです。

稚拙な説明で申し訳ございませんが、何卒よろしくお願いいたします。

◆追記

環境:Microsoft Visual Studio Community 2019 Version 16.7.2

エラーメッセージ:Bull様が提示してくださった通り、
Debug Assertion Failed!
Expression: (L"Buffer is too small" && 0)
と表示されます。

コード:dodox86様、Bull様のおっしゃる通り、
上記のコードを編集し、現在は以下の通りです。
scanf,gets等はscanf_s等、対応するものに書き換えました。

/* filemapping01.c */

\#include <stdio.h>
\#include <windows.h>
\#include <conio.h>

int FRead(LPSTR);
int FWrite(LPSTR);

HANDLE hFMWrite;

int main()
{

static LPSTR lpAddress1, lpAddress2;

int szNo=0;
BOOL bEnd = FALSE;

while (1) {
printf("***********\n");
printf("1. Writre\n");
printf("2. Read\n");
printf("0. End\n");
printf("***********\n");
printf("No. = ");
scanf_s("%d",&szNo);

switch (szNo) {
case 1:
FWrite(lpAddress1);
break;
case 2:
FRead(lpAddress2);
break;
case 0:
bEnd = TRUE;
break;
default:
printf("正しくない番号です\n\n");
break;
}
if (bEnd)
break;
}

if (hFMWrite) {
if (CloseHandle(hFMWrite) == 0)
printf("書き込みハンドルクローズ失敗\n");
else
printf("書き込みハンドルクローズ成功\n");
}

return 0;
}

int FWrite(LPSTR lpStr)
{
char szStr[1024];

if (!hFMWrite)
CloseHandle(hFMWrite);

hFMWrite = CreateFileMapping(
(HANDLE)-1,
NULL,
PAGE_READWRITE,
0,
1024,
"NEKODEMOWAKARU");
if (hFMWrite == NULL)
return -1;
if (GetLastError() == ERROR_ALREADY_EXISTS)
printf("すでにマッピングオブジェクトが存在しました\n");

lpStr = (LPSTR)MapViewOfFile(hFMWrite,
FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (lpStr == NULL)
return -2;

printf("書き込み==");
scanf_s(szStr,1024);
strcpy_s(lpStr,1024, szStr);
strcat_s(lpStr,1024, "\n");

UnmapViewOfFile(lpStr);

printf("書き込みました\n");
return 0;
}

int FRead(LPSTR lpStr)
{
HANDLE hFM;

hFM = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "NEKODEMOWAKARU");

lpStr = (LPSTR)MapViewOfFile(hFM,
FILE_MAP_ALL_ACCESS, 0, 0, 0);

if (lpStr == NULL) {
printf("受信失敗\n");
CloseHandle(hFM);
return -1;
}
printf(lpStr);
if (UnmapViewOfFile(lpStr) == 0) {
printf("読み込み用アドレスアンマップ失敗\n");
}
else {
printf("読み込み用アドレスアンマップ成功\n");
lpStr = NULL;
}

CloseHandle(hFM);

return 0;
}

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Bull

    2020/09/25 15:25

    エラーメッセージは
    Debug Assertion Failed!

    Expression: (L"Buffer is too small" && 0)
    でしょうか?

    もしそうであれば、参考サイトのソースから strcpy を strcpy_s に変更していますか?
    そして、どのように変更したのでしょうか?

    キャンセル

  • tmykbys

    2020/09/25 21:07 編集

    皆様、情報不足により大変失礼いたしました。
    早速追記いたしましたので、お目通しいただければ幸いです。
    何卒よろしくお願い申し上げます。

    キャンセル

  • dodox86

    2020/09/26 03:41

    回答はしましたが、質問文中でもコードを載せるときはマークダウン記法を用いて読みやすくするようにしてください。インデントも崩れ、読みづらいとそれだけで回答は離れがちになります。
    https://teratail.com/help/question-tips#questionTips3-5-1
    https://teratail.com/questions/238564
    あたりを参考にしてソースコードを適切に表示するようにしましょう。

    キャンセル

回答 1

checkベストアンサー

+2

l buffer is too small && 0
等のエラーが発生しました。

エラー(実際にはAssertion)が発生するのは、修正の仕方が間違っているためです。発生しているのはFWrite関数の以下の部分です。

printf("書き込み==");
scanf_s(szStr,1024);
strcpy_s(lpStr,1024, szStr);
strcat_s(lpStr,1024, "\n");の


scanf、さらにそれを代替したscanf_sでは、書式制御文字列が必要です。この場合は簡単には"%s"を指定します。なぜ「l buffer is too small && 0」のエラーが発生するかと言えば、スタック領域であるszStrの配列の領域にはVisual Studio でのデバッグ実行時、0xccが埋め込まれる為です。これはデバッガー上で見ると"フフフフフ..."の文字列になります。(0xccはシフトJISで半角カタカナの'フ'です)

scanf_sでの引数指定が正しくされていないために、続くstrcpy_sで1024バイトを超えるコピーとなり、エラーになります。scanf_s(szStr,1024)の部分は、scanf_s("%s", szStr, 1024)のように書くのが正しいです。

尚、1024と直接にサイズを記載している部分は、より汎用的な_countofマクロ が使えます。これを適用して修正すると、以下のようになるでしょう。

printf("書き込み==");
scanf_s("%s", szStr, _countof(szStr));
strcpy_s(lpStr, _countof(szStr), szStr);
strcat_s(lpStr, _countof(szStr), "\n");

ついでに書けば、gets関数のより直接的な代替は fgets です。gets(szStr)は、fgets(szStr, _countof(szStr), stdin) と書き替えることができます。


余談:

本題とは関係ないですが、FWrite()関数の導入部、以下のコードは誤りだと思います。

if (!hFMWrite)
    CloseHandle(hFMWrite);


もともとhFMWriteのハンドルが開いていたら閉じる、を意図したコードだと思いますが、 CreateFileMapping で返される有効なハンドルの値はNULL以外なので、

if (hFMWrite)  /* if (hFMWrite != NULL) */
    CloseHandle(hFMWrite);


であるはずです。また、コードの冒頭部分でグローバル変数としてHANDLE hFMWrite;が宣言されていますが、自動的にNULLで初期化済みとは言え、

HANDLE hFMWrite = NULL;


とでもしておいた方がまぁ分かり易いかもしれません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る