2013-03-19 12 views
5

Czy .NET daje gwarancje, że tablice bajtów .NET są zawsze prawidłowo wyrównane? Potrzebuję tego do leczenia np. tablica bajtów w niebezpiecznym kontekście, tak długo, jak w x64, aby zmodyfikować porcje danych z natywnym rozmiarem rejestru.Czy tablice w .NET są naturalnie wyrównane?

Ale do tej pory nie znalazłem żadnej dokumentacji, że CLR daje mi gwarancje, że mój dostęp do pamięci jest wtedy odpowiednio wyrównany.

+1

Może to pomóc: http://stackoverflow.com/questions/9741395/alignment-of-arrays-in-net –

+0

Przyjęta odpowiedź nie dotyczy pierwotnego pytania o wyrównanie tablic. –

+1

W jaki sposób tablice bajtów mogą być źle ustawione? –

Odpowiedz

6

Nie. I faktycznie tablice mogą być źle wyrównane dla jittera x86. Szczególnie problem z podwójnym [] i długim [], śmieciarz daje tylko gwarancję, że będą one wyrównane na poziomie 4. Co wyjaśnia specjalną zasadę podwójnego [], taka tablica zostanie przydzielona w stertę Dużego Obiektu, gdy ma 1000 lub więcej elementów. Znacznie mniej niż normalna reguła dla przydziałów LOH, 85000 lub więcej bajtów. LOH zależy od gwarancji wyrównania sterty systemu Windows, wyrównane na poziomie 8. Nie jest to inaczej problem z jitterem x64.

Trochę bardziej specyficzne dla twojego pytania: tablice bajtów nigdy nie będą problemem. Bajt jest zawsze wyrównany, bez względu na to, gdzie zaczyna się tablica. "Długie" w niezarządzanym kodzie skompilowanym z kompilatorem Microsoft też nie jest problemem, to jest 4 bajty, więc zawsze wyrównuje się z domyślnymi regułami wyrównania GC. W trybie x64 nadal 4 bajty, więc nie ma problemu.

+0

Chcę traktować tablicę bajtów jako tablicę, która wymaga odpowiedniego wyrównania. Tablica bajtów jest tylko medium transportowym w jaki sposób jest ona odczytywana przez .NET. Czy 4-bajtowa reguła wyrównania jest prawdziwa również na x64? W każdym razie nie mogę zakładać naturalnego wyrównania dla tablic bajtowych, które są interpretowane jako różne dane, takie jak longs lub float? –

+0

Nie, jak stwierdzono, nie jest to problemem w x64. Wszystko jest wyrównane do 8, zgodnie z wymaganiami dla odwołań do obiektów, które są 8 bajtami w 64-bitowym kodzie. –

+2

Dziękuję za tę szczegółową odpowiedź. Zawsze zastanawiam się, skąd znasz takie rzeczy bez posiadania pełnego kodu clr w twoim umyśle. –

0

Obiekty .NET (z których tablice są gatunkami) są zawsze wyrównane na podstawie rozmiaru wskaźnika (na przykład 4 bajtowe lub 8 bajtowe wyrównanie). Tak więc wskaźniki obiektów i tablice obiektów są zawsze wyrównane w .NET.

Należy również zauważyć, że dereferencja wskaźnika w .NET nie wymaga wyrównania. Będzie jednak wolniej. na przykład jeśli masz ważny bajt * wskaźnik i który wskazuje na danych, która jest co najmniej osiem bajtów długości, można rzucić go na długo * i uzyskać wartość:

unsafe 
{ 
    var data = new byte[ 16 ]; 
    fixed (byte* dataP = data) 
    { 
     var misalignedlongP = (long*) (dataP + 3); 
     long value = *misalignedlongP; 
    } 
} 

Czytając kodu źródłowego .NET jest, można zobacz, że Microsoft czasami odpowiada za wyrównanie, a często nie. Przykładem może być metoda wewnętrzna System.Buffer.Memmove (patrz https://referencesource.microsoft.com/#mscorlib/system/buffer.cs,c2ca91c0d34a8f86). Ta metoda ma ścieżki kodu, które odrzucają bajt * do długich bez żadnych kontroli wyrównania w kilku miejscach, a metody wywołujące nie sprawdzają również wyrównania.

Powiązane problemy