「固定」は、ポインター(すなわちint [])をdllsに渡すときに本当に何かを保証しますか?
質問
私はこれを検索しようとしましたが、何も見つかりませんでしたが、ポインターとしてネイティブDLL機能にint []を渡すときには、DLLがポインターへの参照を維持してから、それから試してみることができる危険はまだありません。 「固定」ブロックが終了した後、もう一度アクセスしますか? GCが配列を移動した場合、これはメモリアクセスエラーを引き起こしませんか?もしそうなら、どのようにこれを回避しますか?それとも、これはありそうもないシナリオですか?
解決 2
Here's a class I made to fix the problem. It creates a memory space in unmanaged using AllocHGlobal, and then wraps a pointer to that space. Unfortunately making this generic doesn't seem to work, as there's no way that I can find to cast from void*
to T
in the this[int i]
method.
unsafe sealed class FixedFloatArray : IDisposable {
readonly float* _floats;
internal FixedFloatArray(int size) {
_floats = (float*)Marshal.AllocHGlobal(sizeof(float) * size);
}
internal FixedFloatArray(float[] floats) {
_floats = (float*)Marshal.AllocHGlobal(sizeof(float) * floats.Length);
Marshal.Copy(floats, 0, (IntPtr)_floats, floats.Length);
}
internal float this[int i] {
get { return _floats[i]; }
set { _floats[i] = value; }
}
internal void CopyFrom(float[] source, int sourceIndex, int destinationIndex, int length) {
var memoryOffset = (int)_floats + destinationIndex * sizeof(float);
Marshal.Copy(source, sourceIndex, (IntPtr)memoryOffset, length);
}
internal void CopyTo(int sourceIndex, float[] destination, int destinationIndex, int length) {
var memoryOffset = (int)_floats + sourceIndex * sizeof(float);
Marshal.Copy((IntPtr)memoryOffset, destination, destinationIndex, length);
}
public static implicit operator IntPtr(FixedFloatArray ffa) {
return (IntPtr)ffa._floats;
}
public void Dispose() {
Marshal.FreeHGlobal((IntPtr)_floats);
}
}
他のヒント
アップデート: この質問はの主題でした 2012年12月11日の私のブログ. 。素晴らしい質問をありがとう!
これを検索してみましたが、何も見つかりませんでした
言語について質問がある場合は、言語仕様を読むことを検討してください。
INT []をポインターとしてネイティブDLL機能に渡すとき、DLLがポインターへの参照を維持し、「固定」ブロックが終了した後に再度アクセスしようとする危険はまだありませんか?
うん。言語仕様が述べているように:
固定されたステートメントによって作成されたポインターがこれらのステートメントの実行を超えて生き残れないようにすることは、プログラマーの責任です。たとえば、固定されたステートメントによって作成されたポインターが外部APIに渡される場合、APIがこれらのポインターのメモリを保持しないようにすることはプログラマーの責任です。
GCが配列を移動した場合、これはメモリアクセスエラーを引き起こしませんか?
はい!
もしそうなら、どのようにこれを回避しますか?
あなたはそうしない。 言語仕様が述べているように、 あなたはそれを決してしない必要があります. 。あなたはそれを決してしないので、あなたはそれを回避する方法を見つける必要はありません。むしろ「自分自身を致命的に撃つことから回復するにはどうすればよいですか?」と尋ねるようなものです。あなたはそうしません - あなたが死んでしまいたくないなら、良いルールは「そもそも自分自身を撃たないでください」です。
それとも、これはありそうもないシナリオですか?
管理されたコードのルールに違反するDLLを呼び出すC#プログラムを作成する可能性がありますか? 私 わからない!あなたは私に言います - それはあなたがやりたいと思うようなものですか?