ラベル 失敗談 の投稿を表示しています。 すべての投稿を表示
ラベル 失敗談 の投稿を表示しています。 すべての投稿を表示

2008年8月11日月曜日

インディアン襲来

Windowsではリトルエンディアン。
これで長い時間悩まされたので…

int型をchar型の配列にキャストして演算しているソースがあり

めっちゃ混乱させられました。
以下のソースを実行させてみてください。
結果がわかると思います。
--------------------------
#include

void print(int d, void* bcd){

char* p = (char*)bcd;
int i = 0;
int n = d>>1;
for(i = 0; i< n; ++i) {
printf("%x,",p[i]);
}
}

int main(void) {
int work = 0x12345678;
print(8,&work);
return 1;
}
--------------------------

Windows環境やと。
78,56,34,12
って表示されます。

引数で渡している型と関数内でキャストしている型が違うってどないやねん!
こんな難しいソース書くなといいたいですね…

.

2008年2月6日水曜日

初期化の大切さ改めて実感

初期化していないがためのバグ
コンパイル時の最適化と合わさって
検出にえらい時間がかかってしまった…

問題になったコードの要点だけ抜き出してみた。
C++/CLIでは変数宣言すると勝手に初期化してくれるという
前提やのに。。。動いてなかってん。
------------------------
int i = 0;
for(i = 0; i < 20; ++i) {
int b; // ゼロで自動的に初期化されてるねん♪
b++;
printf("%d\n", b);// 必ず1が出力されることを期待
}
------------------------

ループの中で変数を宣言すると、毎回メモリ確保やん。
効率悪いってのでコンパイラが自動的にループの外で宣言してくれるねん。

↓コンパイル後はこのような意味のコードになってる
------------------------
int i = 0;
int b; // ゼロで自動的に初期化されてるねん♪
for(i = 0; i < 20; ++i) {
b++;
printf("%d\n", b);// 必ず1が出力されることを期待
}
------------------------
そりゃ期待する結果が得られるわけ無いやん…。


変数宣言時に初期化するように修正したコード
------------------------
int i = 0;
for(i = 0; i < 20; ++i) {
int b = 0; // 明示的にゼロで初期化してやった!
b++;
printf("%d\n", b);// 必ず1が出力されることを期待
}
------------------------

コンパイルするとこのような意味のコードになってる
------------------------
int i = 0;
int b; // ゼロで自動的に初期化されてるねん♪
for(i = 0; i < 20; ++i) {
b = 0; // ここが違う!
b++;
printf("%d\n", b);// 必ず1が出力されることを期待
}
------------------------
これで修正完了っと。
他にもコンパイル時の最適化はいろいろあるので覚えておいて損は無いかも。
WikiPedia「コンパイラ最適化」


教訓:
初期化し忘れで出たバグは非常に見つけ難い…(^^;
変数宣言時は初期化する癖をつけよう!

.

2007年9月26日水曜日

アプリケーションの作業フォルダの取得

ディレクトリ削除時に例外が発生した事から
アプリケーションの現在の作業ディレクトリの取得方法を
調べたので残しておきます。

まず発生したメソッドです。
System.IO.Directory.Delete(String)時に IOException が発生した。
MSDNで調べた結果原因は以下通り
1、同名のファイルが存在する
2、アプリケーションの現在の作業ディレクトリである

今回は2の原因だったので
作業ディレクトリ取得方法を調べました。

※補足
1の場合は以下のメソッドで確認しておけば大丈夫なはず。
Directory.Exists(String)

----
// アプリケーションの現在の作業ディレクトリの取得
System.IO.Directory.GetCurrentDirectory()

// ついでに設定方法も
System.IO.Directory.SetCurrentDirectory(String)
----


.

2007年7月3日火曜日

VC2005で作成したバイナリファイルのエラー

VC2005で作成したバイナリファイルを実行すると以下のエラーが出た。

「このアプリケーションの構成が正しくないため、アプリケーションを開始できませんでした。アプリケーションを再度インストールすることにより問題が解決する場合があります。」

へ?
.NETFrameWork2.0はインストールしても同じエラーが出る。
なんで??
調べてみると、どうやらライブラリを動的にリンクかけてるっぽい。
Visual C++ ライブラリのランタイム コンポーネントをインストールする必要があるみたい
ということで取得してインストールするとばっちし動いた!

ダウンロード先
http://www.microsoft.com/downloads/details.aspx?FamilyID=32bc1bee-a3f9-4c13-9c99-220b62a191ee&DisplayLang=ja

アンマネージコードやと
コンパイルオプションの「C/C++」「コード生成」で
/MD オプションを /MT に変更すると大丈夫っぽいけど

マネージコードやと解らんかった。
なんか方法ないもんやろか?

.

2007年6月1日金曜日

フォルダをダブルクリックすると検索ウィンドウが開くように…

フォルダオプションを弄ってたら
フォルダをダブルクリックすると検索ウィンドウが開くように…
右クリックから「開く」ではちゃんとフォルダを開いてくれるのに!!

ってことで調べてみた。
レジストリを弄らないと直らないみたいorz
レジストリを触ると何が起こるかわからないので自己責任のもとで触ってください。

「ファイル名を指定して実行」 から regedit を起動
・HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Directory\shell
・(既定) を右クリック「修正」でデータに none と記入して「OK」をクリックします

同じようにドライバをダブルクリックで検索ウィンドウが開く場合は
フォルダの場合と同じように
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Drive\shellの(既定)のデータを none に修正します

2007年1月13日土曜日

unsinedの減算

C言語にて嵌ってしまったこと。

unsigned int a = 3;
unsigned int b = 1;
unsigned int c = 0;

c = a - b;

てなソースを書いてしまい…
c の値が意味不明な数値に!

原因は、unsigned なのに減算を行ってしまっていた事でした。
signed の場合は最上位1ビットが符号をあらわしている。
そのため、マイナス符号をつけた b は b 値の"2の補数"となる。
その結果、 a - b の期待結果としては 2 という値が欲しいが、
-b 値は 1 の2の補数となっているため
a - b の値は(4294967293)となってしまいました。

unsigned の減算には気をつけましょう。
.

ラベル