「PInvokeStackImbalance が検出されました」って何だ?

むかーしにVS2008Express C#と.NET2.0で作ったアプリの微修正を依頼されたわけです。

でもアメリカへの海外赴任を挟んでいたこともあって当時の開発環境は既に無く、開発環境の再構築からやり直しました。
まあせっかくなのでVS2010Expressと.NET4.0にアップデートしたのですけれども、そうしたらかつて出なかったエラーが出てビルドが通らないじゃないですか。


出たエラーはこちら。
pInvokeStackImbalance MDA | Microsoft Docs

DLLのマーシャライズを失敗しているっぽい。
前はビルドできたのに…。.NET3.5からの新機能なんですかね?
んで適当にググってみたらこのページがヒット。

呼び出し規約をcdeclと明記しなきゃいけなくなったっぽい?
このページのとおり

  • 元:[DllImport("foo.dll")]
  • 新:[DllImport("foodll", CallingConvention = CallingConvention.Cdecl)]

と変更したらビルドが通りました。
うーん。久々のC#は難しいな…。

"ファイル"を捨ててしまいたい

ひとつ前の記事でも書いたけど、極論を言えばIDEがもっと賢くなってくれたら万事解決じゃないか。
そもそもなんでソースコードをファイル分割しなければならないのか。それはスコープを制御したいからだと思うが、それって本当にファイルでしなきゃならんのか。

  1. ソースコードは全てひとつのファイルに格納される
  2. プログラマーはメソッドを書く
  3. プログラマーIDEにてそのメソッドがどのクラスに属すかを指定する
  4. プログラマーIDEにてそのクラスのスコープ(だれが参照できるか)を指定する

こっちのほうがよっぽど直感的じゃないかな。
何でそっちの方向に進化していかないのかしら?

というかこんな研究をどこぞの大学がしてたはずなんだけど、どこだったかなぁ。

関数単位でソースコード管理したいのだけれど…。

お仕事ではCやらC++を使っているわけですが、ソースコード管理にはCVSsvnを使用しています。
CVSはファイルを、svnディレクトリツリー全体を管理対象とするわけですが、「この関数がどのように変更されたか」が知りたい時があります。

これは言語やソフトウェア構成管理ソフトに限らずプログラマーなら誰もが思ったことあると思うんですよね。
なのにコミットログからはファイル単位での差分しか入手できないわけです。
ちゃうねん。もっとミクロな視点で履歴をチェックしたいねん。

なんで既存のソフトウェア構成管理ソフトはそういったクラスビュー、メソッドビューな履歴管理をサポートしてないのかなぁ…。

デバッグしているときに、

  1. あれここ何かおかしいぞ。自分の覚えてるコードと違う
  2. 誰が触ったんだ
  3. ログ確認

で、なんでわざわざファイルビューで確認しなきゃならんのか。メソッドビューでいいのよ?

こんな不満持ってるの私だけですかね。


1関数1ファイルはコーディングしづらそうだしちょっとためらわれます。
誰かいい方法知りませんかね。

型違いの関数ポインタを引数に渡す

C、C++では型が違っても(void* (*)(void*))にキャストしてやれば関数ポインタを引数に渡すことができるみたい(さすがに引数の数は揃えなきゃだけど)。


今会社ではWindowsLinuxのマルチスレッドプログラムを作っています。
で、自社制作した子スレッドを作るクラスをライブラリがあって、その中で

  1. 外部ではAFX_THREADPROC関数にて子スレッド化したい関数を作成(UINT (*)(void*)型)
  2. void* (*)(void*)型にキャスト
  3. ライブラリの引数に指定
  4. ライブラリ内でAFX_THREADPROC型にキャスト
  5. スレッドの作成
    • Windows: AfxBeginThread関数の呼び出し
    • gcc: pthread_create関数の呼び出し

ってしていた。これでmakeが通る。

ちなみにこの話はクラスのメンバ関数ではNG(静的メンバ関数は除く)。
多態性によりアドレスが一意に定まらないためなんだと。

CentOSでfreeGLUT 2.6.0がビルドできない

freeGLUT 2.6.0のソースコードがCentOS4.7でビルドできません。

  1. ./conigure
  2. make
  3. make install

のmakeでエラーが出ます。

./progs/demo/smooth_opengl3.c内に未定義の型があるとかないとか。

ソースコードを読んでみたら、
#if defined(WIN32)
を通る必要があるっぽい。

まあ、とりあえずビルド通ればいいやとソースコード該当部分直前で
#define WIN32 1 // WindowsのVC2008でWIN32=1と表示されたので
を追記。

これでビルドが通るようになった。とりあえず暫定処置としてはこれでいこう。

gccのライブラリ検索パス (CentOS)

CentOSだと/usr/local/libの検索がデフォルトじゃないんだ…。
/usr/local/includeの検索はデフォルトなのに。
不一致気持ち悪い。

Google Testを試してみた

担当した仕事が予定通り終了。しかし次の仕事がなかなか決まらず少し空き時間が出来ました。
ので、ちょっとGoogle Testを試してみました。
レガシーコードへの適用は生半可無い覚悟が必要ですね…。テストを前提としたクラス構造に作り替える必要があります。ある程度分かってはいましたが、こりゃ大変だ。
他のエンジニアを説得する自信ないなぁ。