C / C++」カテゴリーアーカイブ

Visual Studio で C++ のテストをするとき、ブレークポイントを貼れない時のチェックポイント。

みむらです。

相変わらずの長々としたタイトルですが、
このブログ、主に私自身が使うので(ぁ タイトルで内容が把握できた方が都合がいいのです。
・・・RSS リーダーとかで読んでる方ごめんなさい。

今回は、某プロダクトのコードを書いている時にはまった現象。

(環境は Visual Studio 2010 にて検証。


現象:

「ブレークポイントは現在の設定ではヒットしません。このドキュメントのシンボルが読み込まれていません。」
と出て、ブレークポイントを設定しても無効になる。

具体的には、ブレークポイントを貼ったところが実行時に無効状態になり、
マウスでポイントすると、上記メッセージがでる。

 

確認箇所および修正:

Google で検索しますといろいろなサイトがヒットしますが、
それらで指示されている部分をまず確認。

要約しますと次の通り。
(引用元 : http://ameblo.jp/waka21/entry-10289918886.html

・プロパティ構成が「Debug」か。
・Debug 構成でビルドされた lib, dll を使っているか。
・リンカ設定を確認し、きちんと読み込まれるように設定されているか。
・プロジェクトプロパティの構成プロパティ –> デバッグ –> 「デバッガーの種類」が正しく設定されているか。

今回はこれらをチェックしても改善しませんでしたが、以下の設定を確認して解決しました。

プロジェクトプロパティにおいて、
構成プロパティ –> C/C++ –> コード生成 –> 「最小ビルドを有効にする」 が 「いいえ(/Gm-)」
に設定されているかどうか。

ということで、「簡易ビルド /Gm」が有効になっていると、
ブレークポイントが貼れなくなることがありますので、填まっている方は是非確認をしてみてはいかがでしょう。

Visual Studio でのインデントの整形方法。

メモ。

コーディング技法 : http://msdn.microsoft.com/ja-jp/library/aa291593(v=VS.71).aspx

このページを見てみますと、
インデントに関して「空白4個などに定め」とあります。

たぶんタブでもいいんでしょうけれど、何となくタブ幅でまた議論になりますので、
空白4文字にしてみます。

 

というわけで、Visual Studio での設定:

1.「タブの保持」から「空白の挿入」へ変更する。
(なお別の方法にする場合、ここを規約に則った形に設定します。)

image

2.コードを全部選択して、Ctrl-K, Ctrl-F と押す。

・・・コードの量にあわせて時間が掛かりますが、ソースコードがすべて整形されます。


追加メモ:
下記の2つのアドインも入れておくといいかも。

Indent Guides:
http://visualstudiogallery.msdn.microsoft.com/e792686d-542b-474a-8c55-630980e72c30

スクリーンショット

入れますとこういう感じで、ガイドラインがエディタ上に表示されるため、
インデントのスペース数がおかしい場合はここですぐにわかります。

 

Productivity Power Tools :
http://visualstudiogallery.msdn.microsoft.com/d0d33361-18e2-46c0-8ff2-4adea1e34fef/

このアドインは多くの機能がありますが、
(詳細は窓の杜の記事を参照してください。)

空白とタブのインデントがごちゃ混ぜに入っている場合、どちらかに直してくれる機能があります。

image

混ざっているソースコードを開きますと、こういうメッセージが表示され、
Tabify でタブによるインデント、
Untabify でスペースによるインデントに統一されます。

小学生にも情報教育をば。

どうもみむらです。

いきなり質問ですが、下記の2つの文章の共通点をあげてください。

A.里の秋。

静かな静かな 里の秋
お背戸に木の実の 落ちる夜は
ああ 母さんとただ二人
栗の実 煮てます いろりばた

B.静かな湖畔

静かな湖畔の 森のかげから
もう起きちゃいかがと カッコが鳴く
カッコ カッコ
カッコ カッコ カッコ

 

はい、もうわかりましたよね。

こたえは、誰しもがわかるあれです。

続きを読む

Cコード中にマシン語を埋め込んで実行する。

なんだろう、何百番煎じな気がする。もうお茶も出なくなってお湯ですよ、お湯。

フォロワーの @pasberth さんが、「JIT ってどういう仕掛けになってるの!」といっていたので、
メモリ上にバイトコードを置いて実行する方法ということでちょろっと書いたものです。

とりあえず、ピタゴラスの定理をアセンブラで書いて、
C でぺけぺけ。

ひとまず、私の作業環境である Windows での動作確認。

440411299

そいでもって、x86 なら、どのプラットフォームでもバイナリ部分は変えなくても走るよ! ってのを示すために、
Mac を立ち上げて実行。

440460787

 


ソースコードは下記のような感じです。@pasberth さん用に書いたので、Mac 向けソースになってます
Windows で動かすには、先頭の vm_protect を VirtualProtect の形式に書き換えれば動きます。

 

#include <mach/mach.h>
#include <stdio.h>

/************************************************
 とりあえず、中のデータは16進で記録してあって、

リトルエンディアンですから、
 0x01020304 は、メモリ上に 0x04,0x03,0x02,0x01 の順で格納されます。
要は逆順です。

また、命令のオーダーについては、必ずしも何バイトということはありませんが、
最長命令は 32bit アーキテクチャですんで 4 バイト ( 32 bit / 8 = 4 byte. )

見やすくするために、2バイトや1バイト命令に関しては、
0x90 (NOP) [NOP = なにもしない] を挿入して、アライメント(区切り)を合わせてあります。

まー、適当に見てもらえれば。

************************************************/

int main(){
	unsigned long d;
	int a = 0,b = 0,c = 0;
	unsigned long code[32] = {0};
	
	printf("vm_protect : %s\n\n",vm_protect(
		mach_task_self(),
		(vm_address_t)code,32 * sizeof(long),
		FALSE,
			VM_PROT_READ | 
			VM_PROT_WRITE | 
			VM_PROT_EXECUTE
		) == KERN_SUCCESS ? "[OK]" : "[FALSE]");

	printf("INPUT [a,b,c] : ");
	scanf("%d,%d,%d",&a,&b,&c);

	code[0]  = 0x0424448B;	// MOV EAX,DWORD PTR SS:[ESP+4]
	code[1]  = 0x08244C8B;	// MOV ECX,DWORD PTR SS:[ESP+8]
	code[2]  = 0x9090C13B;	// CMP EAX,ECX
	code[3]  = 0x9090047E;	// JLE SHORT ; EIP+4
	code[4]  = 0x9090C88B;	// MOV ECX,EAX
	code[5]  = 0x0C24548B;	// MOV EDX,DWORD PTR SS:[ESP+C]
	code[6]  = 0x9090CA3B;	// CMP ECX,EDX
	code[7]  = 0x9090147E;	// JLE SHORT ; EIP+C
	code[8]  = 0x90909056;	// PUSH ESI
	code[9]  = 0x9090F28B;	// MOV ESI,EDX
	code[10] = 0x9090D18B;	// MOV EDX,ECX
	code[11] = 0x9090CE8B;	// MOV ECX,ESI
	code[12] = 0x9090905E;	// POP ESI
	code[13] = 0x90C0AF0F;	// IMUL EAX,EAX
	code[14] = 0x90C9AF0F;	// IMUL ECX,ECX
	code[15] = 0x90D2AF0F;	// IMUL EDX,EDX
	code[16] = 0x9090C103;	// ADD EAX,ECX
	code[17] = 0x9090C22B;	// SUB EAX,EDX
	code[18] = 0x9090D8F7;	// NEG EAX
	code[19] = 0x9090C01B;	// SBB EAX,EAX
	code[20] = 0x90909040;	// INC EAX
	code[21] = 0x909090C3;	// RETN
	
	printf("\nRETURN : %s\n",
		((int(*)(int,int,int))code)(a,b,c) == 0 ? "[FALSE]" : "[OK]");
	
	return 0;
}

 

中のバイトコード部分は、ソースコード中のコメントを見てもらえれば。

本来、こういうページ領域上にバイトコードを置いて、それを呼び出そうとしても、
実行できないように設定されています。

(実行できるようになっていると、プロセスに脆弱性があったとき、悪意のあるコードを攻撃者から送信されて、実行されてしまう危険性が格段に上がる)

ですが、さすがに完全に実行できないと、Java VM をはじめとしたソフトウェアが稼働できなくなってしまうため、
OSから実行可能にフラグを書き換えるAPIが提供されています。

OS

関数

Windows VirtualProtect
MSDN : http://msdn.microsoft.com/ja-jp/library/cc430214.aspx
Mac OS X vm_protect
The GNU Mach Reference Manual :
http://www.gnu.org/software/hurd/gnumach-doc/Memory-Attributes.html
Darwin :
http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/vm_protect.html
Linux mprotect
Man page of MPROTECT :
http://linuxjm.sourceforge.jp/html/LDP_man-pages/man2/mprotect.2.html

実行可能なバイトコードは、x86 プロセッサ共通なので、同じプロセッサならどれでも動きますが、
各オペレーティングシステムに合わせて、上記に挙げた関数を利用して、実行可能に設定する必要があります。

 

実際の JIT コンパイラなどでは、各プラットフォームごとのライブラリや、
APIの差異の吸収が必要になって、結構面倒なことになりますが、

今回の例はきわめて単純な例を使って、 x86 プロセッサ上なら同じコードが動くということを示すのと同時に、
Java などでは、こういう感じでたぶんコードを実行しているということで。

(mono はこれ使ってる感濃厚。 ソースコードを眺めていた感じでは。

お絵かきソフト作成中だったりします。

無題

 

ども。Mimura です。

 

答辞の文章つくったり、ICTスクールの成果物作ってみたり、
二秒ぐらい逆出校メンバーに混じって掃除手伝ってみたり、

何かと忙しい日々ですが、息抜きということで、新しいソフト作ってます。

 

本当はペンの選択の部分を画像使ってやってみたり、ツールバーセットしてみたり、
元に戻すとかの履歴機能を使えるようにしたり、それ以前にレイヤーを搭載してみたりいろいろとやりたいのですが、まだ出来ていないのが実情です。はい。すいません。

 

今のところ、内部構造としてはレイヤーやキャンバスの概念が搭載されていて、
複数の画像を同時編集したり、大量のレイヤーを使用したりも出来ます。

出来る用にはなっているのですが、インターフェイスの製作が圧倒的に間に合ってません。どうしよう。

 

 

筆圧の入力に対応して、ペンタブレット接続環境では筆圧が反映されます。

そして、このソフト、絵の周りの色選択ツールやペン選択ツールなどのそれぞれのウィンドウが、
それぞれ独立して動くような仕掛けになっていて、
キャンバスやレイヤーが格納されているメイン部分(カーネル)には内部定義してあるメッセージを飛ばしてやりとりする構造となっています。
また、頻繁にアクセスするオブジェクトに関してはエクスポートされている関数を呼び出すことでアクセスできるようになっています。

 

そしてそして、ペンについても同様の構造になっていて、それぞれが独立した物体になってます。

 

なんでそんな構造にしたのかというと、将来的にプラグイン方式を付けたいと思ったため。
そして、絵がへたっぴで、授業の「美術」と聞いただけで身の毛がよだつほどの私ですから、
なるべくそういう部分を、慣れている人に作ってもらえたらいいなぁ。なんて思っていたり思わなかったり。

・・。でもそういう人って大抵、自分でソフト書いちゃいますよね。むぅ。

 

 

ある程度プログラムが固まったら、SDK付きで公開してみようかなぁ。なんてことを考えています。
心優しい方がいましたら、プラグイン作って、すばらしいペンやツールを作ってもらえると有難いです。
プラグインの製作はあんちゅことないですし、デフォルトのツールもあんちゅことないです。

 

 

まぁー。そんな感じで。

とりあえず、現時点では描画時に CPU を 100% 50%取られるので、 (手持ちの Eee PC 901-X にて)
(製作用マシン [C2Q Q6600] では 22%ほど持って行く。)

最適化しないとなぁ。と考えています。 DIB で自分で数式演算書いた方が早いのかなぁ。
それとも DDB で BitBlt とかガリガリやった方がいいのかなぁ。 むぅ。

助言お待ちしています。

 

 

PIC9715.tmp

 

02/10編集。

あ。何寝ぼけてたんだろう。 Eee-PC 901-X は デュアルコアですから、100% 取ることはないです。
(シングルタスクのプログラムのため)

それでも50% 近くは取っていきます。 シングルコアの100%みたいなところですね。

 

隣で眠ってるシングルコアのマシンで動かすと、他のプログラムの処理分が多少ありますが、
合計値としては100%になります。 何れにせよ、構造を見直さないとまずいですよね。