나는 .NET 2.0을 타겟으로하는 SafeBuffer
과 비슷한 클래스를 만들고있다. 함수 중 하나는 배열로 (blittable) 일련의 구조를 읽고 쓰는 void ReadArray<T>(long position, T[] array, int offset, int count)
(또는 WriteArray
)입니다.CLR Blittable 구조체의 정렬 된 크기를 얻는 방법?
내 첫 번째 추측은 과 함께 Marshal.PtrToStructure
/StructureToPtr
을 사용하는 것입니다. 그러나 SafeBuffer.ReadArray
의 일리노이를 보면 발전 (내부 방법)에 Marshal.AlignedSizeOf<T>()
을 사용한다는 것을 알 수 있습니다. 이 함수는 다음과 같이 정의됩니다.
uint s = Marshal.SizeOf<T>();
if (s == 1u || s == 2u || IntPtr.Size == 8 && s == 4u) { return s; }
return Marshal.AlignedSizeOfType(typeof(T)); // an internalcall
이 메서드는 .NET 4.0에서만 정의되어 있으므로 나 (Rotor에서도 사용할 수 없음)로 정의됩니다.
제 아이디어는 배열의 인접 요소에 Marshal.UnsafeAddrOfPinnedArrayElement
을 사용하는 것이지만 작동하지 않습니다. 여기 내 테스트 코드입니다 : (? 기본 AlignedSizeOf가 어떻게 다른지 알) 86 또는 64에 6, 6, 6,
8
를 출력
using System;
using System.Reflection;
using System.Runtime.InteropServices;
namespace test
{
class Program
{
[StructLayout(LayoutKind.Sequential)]
struct A
{
byte a;
short x;
byte b;
}
private static MethodInfo MarshalAlignedSizeOf;
static int MAlignedSizeOf(Type t)
{
if (MarshalAlignedSizeOf == null) { MarshalAlignedSizeOf = typeof(Marshal).GetMethod("AlignedSizeOf", BindingFlags.NonPublic | BindingFlags.Static); }
return (int)(uint)MarshalAlignedSizeOf.MakeGenericMethod(t).Invoke(null, null);
}
static int AlignedSizeOf(Type t)
{
Array a = Array.CreateInstance(t, 0);
GCHandle pin = GCHandle.Alloc(a, GCHandleType.Pinned);
try
{
return (int)(Marshal.UnsafeAddrOfPinnedArrayElement(a, 1).ToInt64() - Marshal.UnsafeAddrOfPinnedArrayElement(a, 0).ToInt64());
}
finally { pin.Free(); }
}
unsafe static void Main(string[] args)
{
Console.WriteLine("sizeof: " + sizeof(A));
Console.WriteLine("SizeOf: " + Marshal.SizeOf(typeof(A)));
Console.WriteLine("aligned size: " + AlignedSizeOf(typeof(A)));
Console.WriteLine("mars algn sz: " + MAlignedSizeOf(typeof(A)));
}
}
}
.
그래서 질문은 다음과 같습니다- 토론 : 이유는 크기가 정상 크기보다 다른 정렬? C/C++에서 sizeof()는 완전히 정렬 된 값입니다. (
sizeof(arr)/sizeof(arr[0])
항상 작동) - blittable 일반 구조체의 정렬 된 크기를 얻으려면 관리되는 방법 (안전하지 않은 코드 사용 또는 사용 안함)이 있습니까?
- 방금
SizeOf()
을 사용해야하며이 추가 정렬에 신경 쓰지 않아도 되나요? 그럴 경우 그냥 블록 전송을 할 수 있습니다 ...
를 얻기 위해 디버거 메모리 창의 주소 상자에 "& 편곡"를 넣어, 나는 11 00 12 00 13 00''01 00 02 00 03 00를 참조하십시오. 내가 왜 다른 것을 볼 수 있는지 모르겠다 ... (x86과 x64, 디버그 모드, .NET 4에서 테스트 됨). 원래 당신이 가지고있는 것과 같은 것을 볼 것으로 예상 되었기 때문에 나는 배열 요소 위치의 차이점을 시험해 보았습니다. – coderforlife
그건. NET 3.5. 제가 지적했듯이 엔지니어를 리버스하는 것은 매우 어렵습니다. –
여전히 정렬 패턴을 재현 할 수 없지만 CLR 엔진에서 "구현 마술"이라고 생각합니다 ... 나는 Marshal.SizeOf'를 사용하여 그런 식으로 저장합니다. – coderforlife