![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?8acaa2e)
コンパイラはVisual C++ 2008 Express Editionです。
以下のようなコードを書くと
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <commctrl.h>
#pragma comment ( lib, "comctl32.lib")
HRESULT InitCOM_Ole32(){ //初期化
HMODULE hDLL( LoadLibrary(_T("Ole32.dll")) );
if (!hDLL) return E_FAIL;
typedef HRESULT (*Func)( LPVOID );
Func func = (Func)GetProcAddress(hDLL,"CoInitialize");
HRESULT hr( func( 0 ) );
FreeLibrary( hDLL );
return hr;
}
void UnInitCOM_Ole32(){ //後始末
HMODULE hDLL( LoadLibrary(_T("Ole32.dll")) );
if (!hDLL) return;
void (*func)() = (void (*)())GetProcAddress(hDLL,"CoUninitialize");
func();
FreeLibrary( hDLL );
}
int main(){
InitCOM_Ole32();
InitCommonControls();
UnInitCOM_Ole32();
getchar();
return 0;
}
最適化オプションが無効なら問題ないのですが、最適化オプションを付けると
getchar();
直後に落ちてしまいます。
また、別のプロジェクトでも、最適化オプションなしなら正常に動くのですが、最適化オプションを付けると、そちらは初期化関数サイドを抜ける瞬間には落ちてしまいます。
アセンブリ出力を見ても、関数名とかはそのまま書かれている分に感じるので、どこがまずいのかよく分かりません。
これらはどのように対処すればいいのでしょうか?
あるいは、書き方自体が間違っている(未定義動作になる)部分があるのでしょうか?
No.2ベストアンサー
- 回答日時:
WindowsAPIの呼び出し規約はstdcallで、VC++のデフォルトの呼び出し規約はcdeclです。
ですので、stdcallを指定しなければ、stdcallの関数をcdeclで呼んでしまいおかしなことになります。
ですので、
typedef HRESULT (__stdcall * Func)( LPVOID );
みたいにする必要があります。
WindowsAPIならこっちの方が良いかも知れません。
typedef HRESULT (WINAPI * Func)( LPVOID );
なるほど!
そういえば数回無意識に触れていたようですが、呼び出し規約という概念自体、あまりよく知らなかったです。
これを機に調べてみて納得しました。
また、jgkさんのおっしゃる通りWindowsAPI用に呼び出し規約を指定することで、どちらのプロジェクトも問題なく動作するようになりました。
ただ、質問文のコードのLoadLibrary、FreeLibraryの使い方が、この場合は問題ないのかあるのかはやはり気になるので、最大で数日程度締め切りを待たせてください。
No.1
- 回答日時:
CoInitializeとCoUninitializeを別の
インスタンスで実行して大丈夫なんですか?
普通に考えると気持ち悪いですね。
何かMSのドキュメントで保証されているので
しょうか?
同じインスタンスで実行するようにhDLLを
大域変数として、後処理でのみFreeLibraryを
実行するように修正してみたらどうなりますか?
ありがとうございます。
分かりやすくグローバルな位置(とかただの名前空間内)に持ってきて、初期化サイドから
FreeLibrary
を
後始末サイドから
LoadLibrary
を消して「最適化オプション付き」でやってみると、今度は「初期化関数を抜けるときに」確実に落ちるようになりました。
最適化オプションなしならやはりhDLLが同じ変数であってもなんら問題はありません。
LoadLibraryについて
http://msdn.microsoft.com/ja-jp/library/cc429241 …
HMODULEというのは文字通りモジュールハンドルなのでDLLを必要に応じてロードしたり解放したり、というのは意味的にも問題ないと思っていましたが、逆に(COMの初期化、後始末が関係するという点で)上記質問文のコードの場合は問題がある、という記述はあるのでしょうか?
いちおう質問文でのコードではアドレスが一致するか調べてみましたが
TCHAR c[100];
_stprintf_s(c,100,_T("%p"),hDLL);
_tprintf(c);
別のインスタンスで実行して、同じアドレスが得られました。
やはり最適化でどっかが浸食されてるんじゃないかな…
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# Cのオブジェクトファイルの逆アセンブル 5 2023/05/13 01:51
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- その他(プログラミング・Web制作) python flask から fastapiへの移行時のエラー対処 1 2023/02/05 12:26
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# カードシャッフルのブログラムを使ってc言語でブラックジャックをしたい 2 2022/04/12 15:13
- Ruby 教えてください 2 2023/01/04 17:50
- C言語・C++・C# C言語初心者 構造体 課題について 1 2023/03/10 19:30
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
既定のコンストラクタがありま...
-
戻り値を返す関数の前に(void)...
-
void*型の配列について
-
VC++でGetKeyboardStateがうま...
-
C++にてtemplateで受け取った任...
-
静的でないメンバ関数の呼び出...
-
多重定義が起きている?--lnk20...
-
【gcc・cygwin】multiple defin...
-
C# Controls.Addで動的に配置し...
-
プログラムを教えてください。...
-
gcc: incompatible pointer type
-
int main()、void main()、void...
-
C++でオーバーロードに関するバ...
-
最適化オプションと LoadLibrar...
-
組み込みマイコン
-
OpenSSLのSHA1関連の関数はどこ...
-
C言語 extern について
-
const_castのつかいどころを教...
-
privateなnamespaceメンバ
-
(void)0 はどんな意味ですか
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
既定のコンストラクタがありま...
-
【gcc・cygwin】multiple defin...
-
戻り値を返す関数の前に(void)...
-
C++にてtemplateで受け取った任...
-
多重定義が起きている?--lnk20...
-
gcc: incompatible pointer type
-
静的でないメンバ関数の呼び出...
-
int main()、void main()、void...
-
Notepad++の関数リスト表示の変...
-
C# KeyDownイベントでショート...
-
C# Controls.Addで動的に配置し...
-
ArduinoでMouse関数を使用して...
-
(void)0 はどんな意味ですか
-
DLLの関数呼び出しで引数がある...
-
void*型の配列について
-
ウインドウの移動禁止
-
const_castのつかいどころを教...
-
VC++でGetKeyboardStateがうま...
-
C言語 プロトタイプ宣言
-
stddef.hって何?
おすすめ情報