0

こんにちは、malloc によって割り当てられたメモリのチャンクを取得し、後で非同期に割り当てを解除するア​​ンマネージ関数があります。マネージドラッパーにラップしたい。次のコードは大丈夫ですか?

void managed_fx (byte data __gc[], size_t size)
{
    //  Pin the data
    byte __pin *pinned_data = &data [0];

    //  Copy data to the unmanaged buffer.
    void *unmanaged_data = malloc (size);
    memcpy (unmanaged_data, (byte*) pinned_data, size);

    //  Forward the call
    fx (unmanaged_data, size);
}
4

5 に答える 5

2

私の MC++ は少し錆びていますが、__pin は "pinned_data" が範囲外になるまでソース変数を固定していると思います (少なくとも、C++/CLI の同等の pin_ptr がそうです)。一般に、できるだけ早く固定を解除する必要があります。つまり、パフォーマンス上の理由から、同じスコープで fx を呼び出すべきではありません。

この場合、固定はまったく必要ですか?

はい。アンマネージ コードからマネージ メモリにアクセスする場合。

memcpyの前にGCで割り当てを解除できますか

いいえ。データへの強力な参照があるため、gc はそれを収集しません。ただし、他のオブジェクトを収集し、圧縮手順でメモリ内のデータを移動する場合があります。その場合、malloc は間違ったメモリ領域にアクセスします。ピン留めはこれを防ぎますが、GC の追加の簿記を犠牲にします (そのため、できるだけ早くオブジェクトのピン留めを解除する必要があります)。

マネージド コードで使用されている場合でも、malloc はアンマネージド メモリを割り当てますか?

はい。

于 2009-01-23T15:47:49.407 に答える
0

あなたは

  1. データ配列が少なくとも同じサイズであると仮定します。これは発生するのを待っている可能性のあるバグです

  2. malloc()の結果をチェックしない

  3. とにかくこれを行う必要はないかもしれません。ピン留めされたバイトポインタを渡すだけで問題ありません(呼び出されたfx()関数が何らかの方法でデータを変更する場合を除きます。その場合、コピーが必要になる可能性があります)。後で解放されるメモリに基づいて、これは可能性ではない可能性があります。

それを念頭に置いて、ここに修正されたバージョンがあります

void managed_fx (byte data __gc[], size_t size)
{
    if (data.Length < size)
        throw gcnew System.IndexOutOfRangeException(
            "the unmanaged buffer is not big enough");
    //  Pin the data
    byte __pin *pinned_data = &data [0];

    //  Copy data to the unmanaged buffer.
    void *unmanaged_data = malloc (size);
    if (unmanaged_data == NULL) 
        throw gcnew OutOfMemoryException(
            "could not allocate memory for the unmanaged buffer");
    memcpy (unmanaged_data, (byte*) pinned_data, size);

    //  Forward the call
    fx (unamanged_data, size);
}

さらなる質問に答えるには:

memcpyを実行するには、ピン留めが必要です。GCランタイムによるメモリの削除を防ぐことはできません(技術的にはそうですが、単にメモリへの参照を保持することもできます)。メモリ内での移動を防ぎます。memcpyはアンマネージ関数であるため、操作しているポインターをメモリ内で移動して処理することはできません。mallocは完全に管理されていません(ただし、ランタイムライブラリは管理対象ヒープの予約済み領域を自由に使用してこれを行うことができます)。

'コード'が管理されているか管理されていないかに関して、ソースC ++/CLIには明確な区別はありません。コンパイル時に、一部の部分はCIL中間コードになり、他の部分はプレーンなネイティブコードになります。重要なのは、変数が使用されるのは管理されているか、管理されていないかです。管理された参照(^が付いているもの)は、それ自体が管理されているコードによってのみ操作/使用できます。これは、ランタイムがメモリ内の管理対象オブジェクトの場所を変更した場合に、適切と思われる場合に使用される基になるポインタの値を自由に変更できることを意味します。これは、管理対象の機能に対して安全な方法で行われます(機能は、周囲の世界が変化している間は一時停止されます)。このような管理された参照を処理する方法を知らない多くの便利な関数が存在するため、それらへの単純なポインターを取得する必要が生じる可能性があります。この操作は安全ではないため(GCが参照を移動する場合)、ピン留めポインターが存在します。これは、ポインターを取得し、そのポインターの存続期間中、ランタイムがポイントされた変数を移動するのを防ぐため、これを安全かつ簡単に実行できるようにするためです。 。

于 2009-01-23T12:27:56.800 に答える
0

では、さらに簡単にしましょう。

void managed_fx (byte data __gc[])
{
     //  Pin the data
     byte __pin *pinned_data = &data [0];

     //  Copy data to the unmanaged buffer.
     void *unmanaged_data = malloc (data.Length);
     assert (unmanaged_data);
     memcpy (unmanaged_data, (byte*) pinned_data, data.Length);

     //  Forward the call
     fx (unamanged_data, data.Length);
 }

それでも、いくつか質問があります。

  1. この場合、固定はまったく必要ですか? memcpy が発生する前に gc で割り当てを解除できますか?
  2. マネージド コードで使用されている場合でも、malloc はアンマネージド メモリを割り当てますか?
于 2009-01-23T15:32:14.603 に答える
0

実際にポインタが割り当てられていることをmallocをテストする必要があります。C++/CLI がわからないので、ピンが機能するかどうかわかりません。コピー中にメモリが固定されることを保証するために、マーシャリング ライブラリを使用する必要はありませんか?

于 2009-01-23T08:12:55.440 に答える
0

管理されていないデータを割り当てる方法については、こちらをお読みください。マーシャルクラスを見てください。managed_fx 関数を置き換えることができる方法があるかもしれません。

于 2009-01-23T08:17:47.973 に答える