現在C言語で,関数ポインタ型による関数の呼び出しを勉強しています.
print()という関数は受け取った文字列を表示するだけの関数ですが,
これを通常の関数ポインタを用いて実行したのがmain内の(*mem)("FROM POINTER.");です.
これに対して後半は,mallocで確保した領域にmemcpyでprint()をコピーし,
(*mem)("FROM COPIED AREA.");で実行しています.
実行環境は以下の通りです.
OS:Windows7 Personal 32bit
CPU:Intel Core i5 M430
統合開発環境:Visual C++ 2010 Express Edition
コンパイルには成功しています.
実行すると"FROM POINTER."は表示されるのですが,
"FROM COPIED AREA."は表示されず,プログラムが動作を停止してしまいます.
mem = (void (*)(char*))tmp;までは実行できているようですが,
(*mem)("FROM COPIED AREA.");の実行の時点で停止しているようです.
またコマンドプロンプトからBorland C++ 5.5.1でコンパイルしても,
同じように動作が停止してしまいます.
ただし同じプログラムでも,Cygwinからgccでコンパイルすると,
意図した通りの挙動となっていることを確認しています.
コンパイラの違いによるものなのか,
UNIXとWindowsの違いによるものなのか判断できずにいます.
(もしくはライブラリのmalloc,memcpy辺りの実装法の違いでしょうか?)
どなたかご存知でしょうか.
-----------------------------------------
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 512
void print(char* str){
printf("%s\n", str);
}
int main(int argc, char** argv){
void (*mem)(char*);
void *tmp;
mem = &print;
(*mem)("FROM POINTER.");
tmp = malloc(SIZE);
memcpy(tmp, print, SIZE);
mem = (void (*)(char*))tmp;
(*mem)("FROM COPIED AREA.");
}
No.5
- 回答日時:
>セキュリティが堅めだと言われているUNIX系ではこのような書き方が問題ないのに,Windowsでは禁止されているというのは少し不思議です.近い将来,UNIX系でも機械語の挿入によるウイルス実行が流行れば似たような保護機能を付けるかもしれませんね.
もしかしてcygwinでそうだったからUNIX系はそのようになってると思ってらっしゃいますか?
cygwinはライブラリレベルでUNIXをエミュレートしてるだけでUNIXではありませんが。
たしかエミュレートするために色々小細工してたと思いますよ。
UNIX系はmallocの実装にもよりますけどmmapを利用しているのなら、その領域は実行不可に設定されてると思いますし。
>cygwinはライブラリレベルでUNIXをエミュレートしてるだけでUNIXではありません
細部は色々と違うということですか.
No.4の方もテストして下さっていますが,ディストリビューションごとにも違うようです.
UNIXだから,という発想からいったん離れて確認してみます.
ありがとうございました.
No.4
- 回答日時:
Linux(Scientific linux 6)とOSX(10.7)のgccでコンパイルしてみましたが、コンパイラはwarningも出ませんね。
正常に終了しました。実行させると両方ともエラーで落ちます。gdbで確認しましたところ
OSXは(*mem)("FROM COPIED AREA.");
でheap領域に飛ぼうとしたときにbus errotで
Linuxはmemcpy(tmp, print, SIZE);
で落ちます。こちらはなぜ落ちるかはわかりませんが、両方とも実行はできませんでした。
むしろCygwinのメモリ管理の方が問題では。
OSごとに落ちる部分が違って面白いですね.
許可している/禁止しているの違いなのか,
OSが想定している/していないの違いなのか,気になりますね.
Cygwinではなぜ可能なのかということも調べてみます.
No.1ベストアンサー
- 回答日時:
ライブラリの違い…でしょうね。
ちなみに、セキュリティを考慮するとヒープ領域に置いたコードを実行するのは好ましくありません。
# DEP(データ実行防止)の設定によっては動作させようとするとOSに殺されます。
# Windows7なら…[システムのプロパティ]->「詳細設定」タブ->パフォーマンスの[設定]ボタン->「データ実行防止」タブで設定。
また、コード領域にあるものをヒープ領域にただコピーしただけで問題がないか…はライブラリによるでしょう。
今回は別のライブラリ(printf())をコールするだけでしたから、環境によっては問題にならないかも知れませんが、
コピーしたマシン語でアドレスが異なってしまう場合などに吹っ飛びかねません。
# 実行ファイルやDLLはメモリに読み込まれた時点でアドレス再配置が行われますので大丈夫ですが、メモリ上に配置が終わったものの場合は再配置は動作しませんし。
ハードウェアでもDEPはサポートされており,例外を除いてDEPが有効になっていました.コンパイルしたexeファイルを例外に追加しようとしたところ,このプログラムはDEPを有効にして実行する必要があります,と言われてしまいました.そのため重要なプログラムとサービスのみに有効にする設定にして,再起動してから実行してみました.結果は変わらなかったので,DEPが作動して停止したがコマンドプロンプトにその情報が伝わっていないか,OSが動く前にライブラリが原因で動作が停止したのかと思います.
セキュリティが堅めだと言われているUNIX系ではこのような書き方が問題ないのに,Windowsでは禁止されているというのは少し不思議です.近い将来,UNIX系でも機械語の挿入によるウイルス実行が流行れば似たような保護機能を付けるかもしれませんね.
確かにプログラムの配置位置と参照するメモリの位置の関係も,考慮しないといけませんね.本来データ用に後から確保された領域を,命令用に使用するといった手法を用いるウイルスがどうやってこの問題を解決しているのか少し興味がわきました.(私は決して作りません!)
詳しくありがとうございました.
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
- C言語・C++・C# スタックフレームの消滅 6 2023/05/20 12:33
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# Cのdoubleの浮動小数点表示について 3 2023/04/17 13:14
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- その他(プログラミング・Web制作) pythonのプログラムについての質問です。 1 2023/05/26 10:31
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
アプリケーションのDLLファイル...
-
<unistd.h>をVisualStudioでつ...
-
C言語をコンパイルするとコンピ...
-
64ビットのlinuxで32ビットメモ...
-
C#で char型とstring型の比較で...
-
c言語です コンパイルした時に...
-
minGWでのopneMPコンパイルにつ...
-
gccでc++プログラムをコンパイ...
-
リトルエンディアン、ビッグエ...
-
WindowsでコンパイルできるがUN...
-
arduinoのエラーメッセージ
-
コマンドプロンプトを使ったコ...
-
latex cite, ref
-
#If VBA7 Thenに関して
-
VBAにおいて「デバッグ」と「コ...
-
Cコンパイラ(gcc)について
-
VBA と コンパイル の関係
-
プレコンパイルの意味を教えて...
-
#If True Then の # って何??
-
VC++.NET と UTF-8
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
<unistd.h>をVisualStudioでつ...
-
アプリケーションのDLLファイル...
-
C言語をコンパイルするとコンピ...
-
実行後にコンパイルに失敗しま...
-
math.hに含まれる関数が使えない
-
ビープ音が鳴りません・・・
-
c言語です コンパイルした時に...
-
<math.h>ヘッダを入力している...
-
C#で char型とstring型の比較で...
-
共有ライブラリの内容確認について
-
すべてのリビルド: 0 正常、 0 ...
-
[COBOL] ソースの復帰
-
64ビットのlinuxで32ビットメモ...
-
VS2010環境で2点ほど質問
-
gcc バージョン違いによるコン...
-
ヘッダーファイル『windows.h』...
-
C言語で作ったらWindowsでもMac...
-
自作DLLの中身を暗号化
-
MVSマシンで0C7でABENDしたので...
-
Verilog_HDLでのdefineとifdef
おすすめ情報