포인터(예: 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);
        }
    }

다른 팁

업데이트: 이 질문이 주제였습니다 2012년 12월 11일 내 블로그.좋은 질문에 감사드립니다!


이것을 검색해 보았지만 아무것도 찾지 못했습니다

언어에 대한 질문이 있는 경우 언어 사양을 읽어보세요.

int[]를 기본 DLL 함수에 포인터로 전달할 때 DLL이 포인터에 대한 참조를 유지한 다음 "고정된" 블록이 종료된 후 다시 액세스를 시도할 위험이 여전히 있습니까?

네.언어 사양에 따르면 다음과 같습니다.


고정 진술로 만든 포인터가 해당 진술의 실행을 넘어서 살아남지 못하도록하는 것은 프로그래머의 책임입니다.예를 들어, 고정 된 명령문으로 생성 된 포인터가 외부 API로 전달 될 때, API가 이러한 포인터의 기억을 유지하지 않도록 프로그래머의 책임입니다.


GC가 배열을 이동한 경우 메모리 액세스 오류가 발생하지 않습니까?

예!

그렇다면 이 문제를 어떻게 해결합니까?

당신은 그렇지 않습니다. 언어 사양에 따르면, 넌 절대 그렇게 하면 안 돼.당신은 결코 그렇게 하지 않을 것이기 때문에, 당신은 그것을 피할 방법을 찾을 필요가 없습니다.오히려 "치명적인 촬영에서 어떻게 회복합니까?"라고 묻는 것과 같습니다. 당신은 당신이 죽지 않기를 원한다면, 좋은 규칙은 "처음에 자신을 쏘지 마십시오"입니다.

아니면 가능성이 낮은 시나리오인가요?

관리 코드 규칙을 위반하는 DLL을 호출하는 C# 프로그램을 작성할 가능성이 있습니까? 모르겠어요!당신이 말하길, 그것이 당신이 하고 싶은 유혹을 받을 수 있는 일이라고 생각합니까?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top