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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

7回答

5070閲覧

C++ メモリ共有 について

manbo

総合スコア114

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

2グッド

0クリップ

投稿2016/03/19 12:19

C++ で「Windows のアプリケーション間の連携を」学習しているのですがいまいちわかりません。

C++ のメモリ共有というものでできるらしいのですが、参考にしているサンプルコードがコンパイルできず先に進めません。。

なかなかこのあたりの情報がなく学習が進みません。。こちらでは以前先達の方々にやさしく教えていただけてるので、また質問させていただきました。。

下記コードを動くことを確認した上で、サンプルコードをいじったりして学習したいと思っています。

当方プログラミング初心者(非プログラマー&趣味レベル)ですので、わかりやすく教えていただけると幸いです。よろしくお願いいたします。

(環境)
Visual Studio Community 2015 / C++

参考サイトのコードはこれ

/* 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; char szNo[8]; BOOL bEnd = FALSE; while (1) { printf("***************\n"); printf("1. Writre\n"); printf("2. Read\n"); printf("0. End\n"); printf("***************\n"); printf("No. = "); gets(szNo); switch (szNo[0]) { 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("書き込み=="); gets(szStr); strcpy(lpStr, szStr); strcat(lpStr, "\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; }

引用:第114章 メモリマップトファイル その1

(エラー内容)
● 'gets': 識別子が見つかりませんでした

●'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

KiyoshiMotoki, Manabu_K👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答7

0

'gets': 識別子が見つかりませんでした

gets()セキュリティの観点から危険な関数であり、Visual Studio 2015以降で廃止されました。代わりに下記のように書き換える必要があります。

c

1fgets(szNo, sizeof(szNo), stdin);

'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

メッセージどおり、プログラム先頭に #define _CRT_SECURE_NO_WARNINGS とすれば警告が表示されなくなります。

投稿2016/03/19 12:45

yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

manbo

2016/03/20 03:50

yohhoyさん 早速コメントいただき誠にありがとうございます。 そういうことでしたか、gets()はそもそも使えなくなっていたんですね。 解決法もご記入いただきありがとうございます。 おかげさまで、エラーは消えました。 ただ、strcat()については、警告ではなくエラーでして、#defineでは消えませんでした。strcat_s()によって自己解決できましたので、後程書かせていただきたいと思います。 とても参考になりました。ありがとうございました。
guest

0

ベストアンサー

エラーはメモリ共有などには特に関係のない内容です。
getsはバッファオーバーランを簡単に起こす危険な関数のため最新のC言語の仕様から削除されました。
そのためVS2015でもgetsは削除されているので関数がないとなります。
fgetsで同じことをできるのでgetsをそちらに置き換えてください。

gets(szNo)

fgets(szNo, sizeof(szNo), stdin);

2つ目のワーニングですが、strcatも気を付けないとバッファオーバーランを起こすのであまり推奨されておらず代わりに安全な strcat_s を使ってね、というものです。学習中というだけならいったん無視しておいても大丈夫です。
このワーニングがうっとうしかったらプロジェクトのプロパティから C/C++ -> プリプロセッサにあるプリプロセッサの定義に_CRT_SECURE_NO_WARNINGSを追加することで出なくなりますよ。

投稿2016/03/19 12:47

toki_td

総合スコア2850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

manbo

2016/03/20 04:02

tokiさん さっそくコメントいただき誠にありがとうございます。 そういうことだったんですね。そもそもgets()がなくなっていたんですね。しかもVS2015からとは初心者にはなんとも不運でした。 strcat_sも教えていただきありがとうございます。プリプロセッサがどうやるのかわからなかったので、strcat_sを使って自己解決いたしました。のちほど自己解決を書きたいと思いますので、まずいところがあればぜひご指摘をお願いいたします。
guest

0

ご回答をくださった方々、迅速なご回答誠にありがとうございました。

以下に解決を書かせていただきます。じつはgetsをfgetsで回避することができましたが、strcatは、警告ではなくエラーになっており #define では回避できませんでした。ですので、ご教示いただいたとおり、strcatはstrcat_sによって回避することができました。

以下がやったことです。getsはfgetsにstrcatとstrcpyに_sを付けて、引数にキャラ型のbufを追加しました。エラーは回避し「'buf': ローカル変数は 1 度も使われていません」という警告はでたもののプログラムは正常に動作しました。もしまずいところがあればぜひご指摘お願いいたします。

●gets(szNo); → fgets(szNo, sizeof(szNo), stdin);

●strcat(lpStr, "\n"); → strcat_s(lpStr, sizeof(buf), "\n");

●strcpy(lpStr, szStr); → strcpy_s(lpStr, sizeof(buf), szStr);

(以下が修正版です)

/* Visual Studio Community 2015*/ /* Source.cpp */ //#include <stdio.h> #include <iostream> #include <windows.h> #include <conio.h> int FRead(LPSTR); int FWrite(LPSTR); HANDLE hFMWrite; int main() { static LPSTR lpAddress1, lpAddress2; char szNo[8]; BOOL bEnd = FALSE; while (1) { printf("***************\n"); printf("1. Writre\n"); printf("2. Read\n"); printf("0. End\n"); printf("***************\n"); printf("No. = "); //gets(szNo); fgets(szNo, sizeof(szNo), stdin); switch (szNo[0]) { 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; char buf[30]; printf("書き込み=="); //gets(szStr); //strcpy(lpStr, szStr); //strcat(lpStr, "\n"); fgets(szStr, sizeof(szStr), stdin); strcpy_s(lpStr, sizeof(buf), szStr); strcat_s(lpStr, sizeof(buf), "\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; }

投稿2016/03/20 04:51

編集2016/09/17 16:00
manbo

総合スコア114

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yohhoy

2016/03/23 06:16

strcpy_s/strcat_sの第二引数が不適切です。正しくは第一引数に渡したバッファ(lpStr)のサイズを指定すべきです。この例ではCreateFileMappingで作成した1024バイトのファイルマッピングオブジェクトサイズになるかと思います。
退会済みユーザー

退会済みユーザー

2016/03/26 02:50 編集

xx
manbo

2016/03/26 02:54

yohhoyさん 改訂ポイントをお教えいただき誠にありがとうございます。 大変参考になりました。
guest

0

すでに皆さん回答されている内容でエラーは回避できると思いますので、別の観点でひとこと。

参考にされているサイトは私もかつてはお世話になったものですが、さすがにすべての記事を更新し続けることはできないでしょうから情報が古いものも多いです。キャプチャー画像はWindows 2000でしょうか。ものによってはWindows 95時代のものもあるようです。
最初のうちはできるだけ新しい入門書・解説書で勉強するのがお勧めなのですが、ネットの情報だけで勉強されているのだとしたら同じような問題に遭遇する可能性もあるので、いつ書かれた記事なのかということも気にして、情報が古い場合には注意が必要です。

投稿2016/03/19 14:33

catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

manbo

2016/03/20 04:13

catsforepawさん さっそくコメントいただき誠にありがとうございます。 なるほど、このサイトはそんなに前からあるんですね。。。95ということは20年も経つんですか。。そんなに前とは知りませんでした。それは動かないわけですね。その時代からHP上がってるというのもサーバーがずっと動いてるのもなんだかすごいです。 たしかに、おっしゃるように、バージョンやいつの記述かは非常に重要なんだなと最近わかってきました。pythonをいじっていて痛感させられました。ネットの情報はほとんど古くほとんど動きませんでした。
guest

0

こんばんは

実はgets()は今の環境では使えなくなりました(仕様から削除されました).
バッファオーバーフローという言葉を聞いたことありませんか?
gets()はプログラマが想像している以上の入力文字数をもらうと具合が悪く,その対応が出来ないためにこれを使えなくしました(ま,事故防止ですな).

ここだけ修正してもコンパイルは通りませんが,まずは一歩ずついきましょうか

while (1) { printf("***************\n"); printf("1. Writre\n"); printf("2. Read\n"); printf("0. End\n"); printf("***************\n"); printf("No. = "); // gets(szNo); // これはやめる fgets(szNo, sizeof(szNo), stdin); // こんな感じで修正する switch (szNo[0]) { case '1':

投稿2016/03/19 12:52

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

manbo

2016/03/20 04:07

Oh-ZAKさん さっそくコメントいただき誠にありがとうございます。 そういうことだったんですね、事故防止で廃止されたんですね。。そういう情報はやはりベテランの方でないとわからないですよね。学習中の私はこれひとつで何週間も悩んでいて笑、はやくこちらで質問すればよかったとおもいました。。 ありがとうございます。
guest

0

こんにちは。

やってみましたが、コンパイルもできますし、動作もしました。(msvc 2015 update1)
拡張子をcppにしていませんか? C++モードでコンパイルするとエラーになるのだと思います。
拡張子をcにしてC言語としてコンパイルしてみてください。


【余談ですが】
もし、C++を使うのであれば、Cの標準ライブラリ(stdio.h等)を使うのはやめて、C++の標準ライブラリ(iostream等)を使うことをお勧めします。それなりに勉強は必要ですが、安全性が飛躍的に高まります。
Windows APIはCの時とほぼ同じように呼べます。

投稿2016/03/19 12:48

編集2016/03/19 12:50
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

manbo

2016/03/20 03:57

chironianさん さっそくコメントいただき誠にありがとうございます。 なるほど、このコードはC言語のコードだったんですね。。たしかにファイル名がCとなっていますね。あのサイトのコードはすべてC++だと思っていました。。 確かに、拡張子をCにするとエラーが消えるものがありましたが、違うエラーが続出しました。。いろいろ試してみましたが、CPPに戻して、iostream を使うことにしました。 ありがとうございます。
Chironian

2016/03/20 05:09

? 不思議ですね。 私は、Visual Studio 2015 update1を使い、cl filemapping01.cでコンパイルしました。 しかし、Cに拘っても得るものはありませんので、その方針がお薦めです。
guest

0

どのプロジェクトで作成したのかによって変わってきますが・・・。
・Win32プロジェクト
・コンソール アプリケーション
追加のオプションは、
空のプロジェクト
Security Development Lifecycle (SDL)チェックは外す
共通ヘッダーファイルを追加は、すべてチェック外す
で作成したプロジェクトで書いてますか?

投稿2016/03/19 12:46

lib

総合スコア446

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

manbo

2016/03/20 03:53

libさん さっそくコメントいただき誠にありがとうございます。 プロジェクトの作成は、C++のコンソールアプリケーションで空の状態からつくっていました。 ちなみに、SDLチェックは外しても問題ないのですか??
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問