• 締切済み

マネージコードから呼び出したネイティブDLLの動作中のガーベジコレクシ

マネージコードから呼び出したネイティブDLLの動作中のガーベジコレクション C++/CLIの勉強をしていますが、固定ポインタのところで疑問に思うことがあります。 手元の書籍では、ネイティブDLLを呼び出し中にガーベジコレクションが発生すると、 変数のポインタが変わるため、ポインタを固定にすると記されてありました。 ここの部分が疑問です。 ネイティブDLLの動作中は、中間言語は働かないので、 ガーベジコレクションも発生しない気がするのですが・・・。 ネイティブDLLでポインタを記憶した後に、マネージコードでガーベジコレクションが発生して、 記憶したポインタが無効になるのを防ぐというものなのでしょうか?

みんなの回答

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.1

C++/CLIを良く知らないので間違っているかもしれませんけど、一般にはガーベジコレクションを別スレッドで動作させることは可能ですし、そうするとネイティブDLLを実行中でも別スレッドでガーベージコレクションすることは十分にあります。 なお、ネイティブDLLでポインタを記憶するなら、ネイティブDLLを呼び出すときだけでなく最初に呼び出してからネイティブDLLが不要になるまでポインタを固定しておく必要があるでしょう。

_hitoshi_
質問者

お礼

別スレッドで中間言語が働いているとは思いつきませんでした。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • .NET C++/CLIのガーベジコレクションについて

    .NET C++/CLIのガーベジコレクションについて .NET C++/CLIで、マネージピープの配列をネイティブDLLにポインタ引数として渡す動作で、 配列が正常に渡っていることは確認したのですが、ネイティブDLL側で配列の処理をしている最中に、 ガーベジコレクションが起こり、誤動作することはあるのでしょうか。 ちなみに、マーシャリングは以下のように行いました。 // マネージ側コード [DllImport("native.dll")] void ArraySet( [MarshalAs(UnmanagedType::LPArray)] array <int> ^ Data ); array <int> ^ Data = gcnew array <int>(64); ArraySet( Data ); // この中で配列の処理中にガーベジコレクションが起こると誤動作?

  • x64ネイティブコードのDLLはVBAから呼びだせない?DLLが見つからない?

    VC+2005でx64ネイティブコードを出力し、DLLを作成したのですが C:\WindowsフォルダにそのDLLを入れて、いつもどおりVBAから呼びだそうとすると、該当するDLLがありません。と表示されます。 同じように置いているのに無いというメッセージが理解できないです。 x86(32bit)で生成したDLLなら問題なく動作するのですが・・・ 何か違いでもあるのでしょうか? Declareとかでは呼べないのでしょうか? ちなみにVBAはExcel2003です。 DLLでなくMFCアプリで完全ネィテイブ.EXEを作らないとx64の環境は生かせないのでしょうか?

  • DLLのマルチスレッドの動作について

    今、DLLについて勉強しているのですが動作について、不明点があり質問しています。 単純にDLL内に下記のようにMyFuncという関数があったとします。 (コンパイルは/MTを付けています) MyFunc (){ int i; for(i=0;i<10;i++){ printf("%d\n"); } } これをDLLを呼び出すアプリから複数のスレッドで呼び出したとき、それぞでのスレッド毎に、カウントが増えていきます。 DLLはメモリ共有されると思っているのですが、そうではないのか、いまいちわからない状態でご教授いただければと思っています。 このカウントが別々に増えるのは、コードの領域とデータの領域が別ベルだからと考えればよいのでしょうか? コードは同じ領域を使用して、データは別の領域を使用しているのでしょうか? 次にここで使用しているint iをグローバル変数にすると、カウントはスレッド毎に共有されてしまいます。 グローバル変数にすると、この場合のint iはコードの領域に置かれるということなんでしょうか? ちょっと、的を得ていない質問かもしれませんが、何卒、よろしくお願いいたします。

  • [C++/CLI]マネージコードで配列を作成してネイティブコードの配列にコピーしたい

    Visual C++ 2005のC++/CLIでプログラム作成しています。 C言語で書かれたプログラムを組み込みたい為に、 マネージコードでテキストファイル読み込みをして、2次元配列に格納し、 int型に変換してネイティブコードの配列にコピーしたいのですが、上手く書けません。。 テキスト内容は数字のみで2次元に並んでおり、1文字ずつ配列に入れたいです。 エラー出ているのですが、下記にコードを載せます。 #include<string> #include<vcclr.h> using namespace System; using namespace System::IO; int main(void){ //ファイルオープン StreamReader^ sr = gcnew StreamReader("hoge.txt"); int x, y; //ファイルの内容読込み for(y=0;;y++){ String^ line = sr->ReadLine();   //データ末尾まで読み込んだらループ終了 if(line == nullptr) break;    array<array<String^>^>^ table = gcnew array<array<String^>^>(line->Length);    int X=line->Length;    int Y=table->Length; //読み込んだ内容を表示 Console::WriteLine("<System::String表示>" + table);    //System::Stringのline内容(文字列)をコピーする変数   char tmp[128];   sprintf(tmp,"%s",line);   printf_s("<char配列> tmp=%s\n",tmp); //char*変数の内容表示   array<array<int>^>^ data= gcnew array<array<int>^>(Y,X); //int型に変換 for(x=0;x<X;x++){data[y][x]=atoi(table[y][x]);} } //ファイルのクローズ sr->Close();      return 0; } 汚く読みづらいコードで大変申し訳ありません。。 元はdefineで成分数(X,Y)を宣言していました。 しかし、読み込むファイル内容によって変えたく、arrayでLengthを使いました。 またこれ以外でいい方法がございましたら、どうか教えてください。 どなたか、ご教授よろしくお願いします。

  • C#、C++間のDLLの呼び出しについて

    いつも拝見させていただいております。 さっそくですが、質問致します。 現在、ネイティブなC++ DLLを作成しています。 これを今回、C#のアプリケーションから呼び出すことになりました。 DLL内にはクラスを作成しており、内部にXMLのデータを保持するような クラスを作成しております。(XML操作にはMSXMLを使用しております。) 問題なのはC++アプリケーションから呼び出した時は正常に動作するのですが、C#からの呼び出しの時はC++アプリケーションから呼び出した時には発生していないエラーが検出されます。 エラー内容は System.AccessViolationException 保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。 になります。 エラー内容からしてC++内でのメモリ操作に問題があると 思われるのですが、C++からの実行時には検出されていないので理由がわからずに困っております。 ネイティブなDLLに対してはデバッグも行えないため、手に負えません。 (現在、1行ごとにログを埋め込み、TCHAR型のnewを4byte行っている箇所で処理がストップしてしまっているようです。C++からの呼び出し時には正常に処理される箇所です。) ネイティブなDLLに対してのデバッグ方法や似たような現象にあわれた方がいらっしゃいましたらご助力お願い致します。 ・対象のDLLのクラスは_declspec(dllexport)にてエクスポートを行っています。 ・C#からの呼び出し時にはネイティブなDLLのためC++/CLIで作成したプロジェクトでラッパークラスを作成してアクセスを行っています。 ・C++アプリケーションからの呼び出し時はプロパティの設定でインクルードディレクトリ、LIBファイルの設定等を行って直接DLLを参照して 実行(呼び出し)しています。

  • C言語ソースコードの解析

    私は現在組み込みのプロジェクトに参加おります、新米プログラマです。 既存の処理を理解したうえで設計しなければならないのですが、 元のソースコードに対して設計書が1つもなく、 ソース、ヘッダともにコメントなし、と言う状況です。 動作環境が無いので、ソースコードを解析して動作を理解しようとしています。 しかし、やっていることが複雑でなかなか進みません。 ■ポインタ/関数ポインタの嵐で、ポインタの実体を追っていくと、  30~40階層ほど上まで見なければならない。  (関数コールに、コールバックに、メッセージのやり取り)  関数ポインタを32bit整数の変数にキャストして代入し、  整数から関数ポインタに直したりしている。 ■構造体のメンバに他の構造体へのポインタがあり、  さらにその構造体は他の構造体のポインタを持っていて、  そのポインタが他の構造体の・・ などなど。 こういう複雑な他人のコードをどういう風に解析していますでしょうか? ご教授願います。

  • C++/CLIでネイティブの構造体を使用したい

    すみません。C++の初心者です。 C++/CLIフォームアプリケーションで関数の呼出し画面を作成しています。 既にある(C++ネイティブで作成済み)のヘッダファイルをプロジェクト上にコピー、追加して ヘッダファイル内に書かれている構造体を使用したいのですが、 出来ないのでしょうか? ヘッダファイル(xxx.h)内には以下のような構造体が作成されています。 typedef struct { double pq_base; int iter_max; double eps; int chi_set_flg; int bad_rmv_flg; int obs_slk_flg; int obs_before_flg; int calc_pf_flg; double *chi_val_95_0; double *chi_val_97_5; double *chi_val_99_0; }s_SE_SET; C++/CLIのプロジェクト内にこのヘッダファイルを追加して フォーム内のあるボタンを押された時に、この構造体を参照させてあげたいのですが、 以下の様に構造体変数を定義して s_SE_SET se_set; ビルドを行うと以下のエラーが出ます。 error C4368: 'se_set' をマネージ 'se_project::Form1' のメンバーとして定義できません。 混合型はサポートされていません C++/CLIではネイティブで定義された構造体は使用出来ないのでしょうか? なにか方法が有るとすればその方法を教えて頂けると嬉しいです。 どなたかご教授頂けませんでしょうか。 よろしくお願い致します。

  • dllを使用しVB側に文字列を返す2

    No.280310の質問の続きになってしまいますが 「VCで作ったdllを使用し VBに文字列を返すことはできますか」 でVCで作ったdllをVBを呼び出す事ができるようになりました。 Declare宣言で疑問に思ったのですが Declare Function TxtCnt Lib "hoge.dll" (ByVal a As String) As Long aはなぜ値渡しなのでしょうか? 変数が書き換えられて戻ってくるので、byrefで指定していました。 それが問題が起こしていた原因一つでした。 ちなみにint型の数値をポインタで渡した場合はbyrefでうまくいきます。 ご教授願います。

  • DLL内部異常発生時、EXEをまきこまれない

     現在、Windows上で動作する、とあるEXEを開発しています。 <EXE実行環境> OS:Window7 32bit <EXE開発環境> MS VC++2008 ※言語は、C++/CLI <DLL開発環境> MS VC++2008 ※言語は、C++ 私自身が携わっているEXEから、必要に応じて、外部委託したDLLを呼出すことを行っています。 現状、結合テストを行っている最中なのですが、この「DLL」がひどいできで、頻繁に異常終了します。 DLL異常終了で、EXEが巻き込まれてしまう為、テスト者に頻繁に呼出されてしまうのを避けたいのです。(このDLLの開発チームというか、開発者が、そもそもテストしたのかどうか疑っているレベルです) 例えば、EXE側で例外トラップ等をしてやることで、DLL内部で発生した異常を完全に捕らえることは可能でしょうか。 また、別途良い方法はないでしょうか。

  • C++/CLIとC#の連携について

    いつも拝見させていただいております。 現在、C++/CLIとC#にて連携を行っているのですが、C++/CLIで作成したクラス配列 がC#側でどのようにすれば受け取れるのか方法がわかりません。 C++/CLIで作成しているクラス配列はSystem::Collections::Generic::Listを使用 して配列化しています。 下記がC++/CLIのソースになります。 List<testClass>^% testClass::GetList() { List<testClass>^ lpTestClassList = gcnew List<testClass>(); testClass^ lpTestClass; lpTestClass = gcnew testClass(); lpTestClassList->Add(lpWatchServiceMasterInfoWrapper); return lpTestClassList; } これをC#側で使用しようとすると下記エラーが発生します。  「この言語によってサポートされていません」 C++/CLI⇒C#間の連携ではListクラスを使用することは不可能なのでしょうか? クラスを配列にして引き渡したいだけなので、他の方法等含めて何か参考になることがありましたら ご教授ください。 よろしくお願い致します。 開発環境  C++/CLI ⇒ DLL(ネイティブなコードを参照するためのラッパー用DLL)  C# ⇒ アプリケーション