Действительно ли «исправлено» гарантирует что -либо при передаче указателей (то есть int []) DLL?

StackOverflow https://stackoverflow.com/questions/1683844

  •  18-09-2019
  •  | 
  •  

Вопрос

Я попытался искать это, но ничего не нашел, однако при передаче 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, которые нарушают правила управляемого кода? я Не знаю! Вы говорите мне - это то, что, как вы думаете, вам может быть соблазн?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top