1

First_Layer

私はVC++6サービスパック6で書かれたwin32dllを持っています。このdllをFirstLayerと呼びましょう。FirstLayerのソースコードにアクセスできませんが、マネージコードから呼び出す必要があります。問題は、FirstLayerが関数の引数としてstd::vectorとstd::stringを多用し、これらの型をC#アプリケーションに直接マーシャリングする方法がないことです。

Second_Layer

私が考えることができる解決策は、最初にVC++6サービスパック6で記述された別のwin32dllを作成することです。このdllを「SecondLayer」と呼びましょう。SecondLayerはFirstLayerのラッパーとして機能します。このレイヤーにはstd::vectorのラッパークラスが含まれているため、std::vectorはこのレイヤーのすべての関数パラメーターで公開されません。std::vectorのこのラッパークラスをStdVectorWrapperと呼びましょう。

このレイヤーは、メモリの割り当てまたは割り当て解除にnewまたはdelete操作を使用しません。これは、内部でstd::vectorによって処理されるためです。

Third_Layer

また、SecondLayerのラッパーとしてVC++2005クラスライブラリを作成しました。このラッパーは、アンマネージドSecondLayerをマネージドコードに変換するという汚い仕事をすべて行います。このレイヤーを「ThirdLayer」と呼びましょう。

SecondLayerと同様に、このレイヤーはStdVectorWrapperを処理するときにnewとdeleteを使用しません。

Four_Layer

さらに、ThirdLayerを呼び出すC#2005コンソールアプリケーションを作成しました。このC#コンソールアプリケーションを「FourthLayer」と呼びましょう。

呼び出しシーケンスの概要

FourLayer(C#2005)-> ThirdLayer(VC ++ 2005)-> SecondLayer(VC ++ 6)-> FirstLayer(VC ++ 6)

問題

System.AccessViolationException:保護されたメモリの読み取りまたは書き込みを試みました」例外がスローされていることに気付きました。これは、SecondLayerの内部std :: vector割り当てメモリが原因で、ThirdLayerがアクセスするのは不正であると思われます。

これは、VC ++ 2005でFirstLayer(シミュレート)とSecondLayerを再コンパイルすると、問題が完全に解消されるためだと思います。ただし、ソースコードがないため、FirstLayerの製品版を再コンパイルすることはできません。

この問題を解決するには、StdVectorWrapperクラスにあるSecondLayerのstd::vector用の共有メモリアロケータをC++で作成する必要があると聞いています。共有メモリアロケータが必要な理由とその仕組みを完全に理解していませんか?何か案が?

コンパイルしてSecondLayerのコードと一緒に使用できる、インターネット上ですぐに利用できるソースコードはありますか?

これにはブーストライブラリを使用できないことに注意してください。

4

3 に答える 3

0

別のソリューションアーキテクチャを検討する必要があると思います。

VC6 stlベクトルと文字列によって生成されるバイナリコードは、多くのstlアップグレードがあるため、より新しいバージョンのVCによって生成されるコードとは異なると思います。このため、dllにはバイナリ互換ではないstd::vectorとstd::stringの2つの実装があるため、アーキテクチャが機能するとは思われません。

私が提案する解決策は、VC6に戻り、純粋なC APIを介して公開するFirstLayer用の新しいラッパーdllを作成することです。このレイヤーは、FirstLayerとバイナリ互換であることを確認するために、VC6sp6を使用してコンパイルする必要があります。次に、Fourth_LayerでPInvokeを使用して、VC6ラッパーDLLにアクセスします。

于 2009-12-09T02:15:09.643 に答える
0

new各実行可能ファイルまたは dll は、特定のバージョンの c ランタイム ライブラリにリンクしています。これには、およびの実装が含まれていますdelete。2 つのモジュールのコンパイラ (VC2005 と VC6) またはビルド設定 (デバッグとリリース) またはその他の設定 (マルチスレッド ランタイムと非マルチスレッド ランタイム) が異なる場合、それらは異なる C ランタイムにリンクされます。あるランタイムによって割り当てられたメモリが別のランタイムによって解放されると、これが問題になります。

ここで、私が間違っていなければ、テンプレート (std::vector や std::string など) が原因で、すぐにはわからないところにこの問題が潜り込む可能性があります。この問題は、テンプレートが各モジュールに個別にコンパイルされるという事実から生じます。

例: モジュール 1 はベクトルを使用し (したがってメモリを割り当てます)、それを関数パラメータとしてモジュール 2 に渡します。次に、モジュール 2 がベクトルを操作してメモリの割り当てを解除します。この場合、メモリはモジュール 1 のランタイムを使用して割り当てられ、モジュール 2 のランタイムを使用して割り当て解除されました。これらのランタイムが異なる場合は、問題があります。

以上のことから、問題が発生する可能性がある場所が 2 つあります。これらの 2 つのモジュールがまったく同じ設定でコンパイルされていない場合、1 つは FirstLayer と SecondLayer の間にあります。もう 1 つは、SecondLayer と ThirdLayer の間でメモリが一方に割り当てられ、他方で割り当て解除された場合です。

どの場所に問題があるかを確認するために、さらにいくつかのテスト プログラムを作成できます。

FirstLayer-SecondLayer をテストするには、SecondLayer 関数の実装を VC6 プログラムにコピーし、通常の方法でこれらの関数を呼び出すのに十分なコードを記述し、FirstLayer に対してのみリンクします。

最初のテストが失敗しない場合、または修正したら、SecondLayer-ThirdLayer をテストします。ThirdLayer の実装を VC2005 プログラムにコピーし、コードを記述して通常の呼び出しを行い、SecondLayer にリンクします。

于 2009-12-06T03:36:22.750 に答える
0

問題の解決策を見つけました。基本的に、私が書いた StdVectorWrapper クラスはディープコピーを実装していません。そのため、StdVectorWrapper クラスに以下を追加してディープ コピーを実装するだけです。

  • コンストラクターのコピー
  • 代入演算子
  • デコンストラクター

編集:代替ソリューション

さらに良い解決策は、std::vector 自体だけでなく、std::vector に含まれるすべての要素に対してclone_ptrを使用することです。これにより、コピー コンストラクター、代入演算子、およびデコンストラクターが不要になります。

于 2009-12-09T08:06:49.017 に答える