Действительно ли «исправлено» гарантирует что -либо при передаче указателей (то есть int []) DLL?
Вопрос
Я попытался искать это, но ничего не нашел, однако при передаче int [] в нативную функцию DLL в качестве указателя, еще нет опасности, что DLL может сохранить ссылку на указатель, а затем пытаться Получите доступ к нему снова после завершения «фиксированного» блока? Разве это не приведет к ошибкам доступа к памяти, если GC переместил ваш массив? Если да, то как вы это обойти? Или это маловероятный сценарий?
Решение 2
Вот класс, который я сделал, чтобы решить проблему. Это создает пространство памяти в неуправляемых с помощью Allochglobal, а затем завершает указатель на это пространство. К сожалению, создание этого общего, кажется, не работает, так как я не могу найти, чтобы бросить из void*
к T
в this[int i]
метод
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);
}
}
Другие советы
ОБНОВИТЬ: Этот вопрос был предметом Мой блог 11 декабря 2012 года. Анкет Спасибо за отличный вопрос!
пытался искать это, но ничего не нашел
Подумайте о чтении спецификации языка, когда у вас есть вопросы о языке.
При передаче int [] в нативную функцию DLL в качестве указателя не существует опасности, что DLL может поддерживать ссылку на указатель, а затем попытаться получить доступ к нему снова после того, как «фиксированный» блок прекратился?
Ага. Как гласит языковая спецификация:
Ответственность за программист - обеспечить, чтобы указатели, созданные с фиксированными операторами, не выживают за пределами выполнения этих утверждений. Например, когда указатели, созданные с помощью фиксированных операторов, передаются на внешние API, обязан программист, чтобы гарантировать, что API не сохраняют память об этих указателях.
Разве это не приведет к ошибкам доступа к памяти, если GC переместил ваш массив?
Да!
Если да, то как вы это обойти?
Вы этого не делаете. Как говорится в языковой спецификации, Вы должны никогда этого делать. Анкет Поскольку вы никогда этого не сделаете, вам не нужно найти способ обойти это. Это скорее как спросить: «Как мне оправиться от смертельной стрельбы?» Вы этого не делаете - если вы не хотите в конечном итоге мертвым, то хорошее правило: «Не стреляй в себя в первую очередь».
Или это маловероятный сценарий?
Скорее всего, вы будете писать программы C#, которые называют DLL, которые нарушают правила управляемого кода? я Не знаю! Вы говорите мне - это то, что, как вы думаете, вам может быть соблазн?