2013-06-17 15 views
9

Mam projekt przenoszę z 32-bitowych okien do 64-bitowego, który zawiera kod, który można uprościć w następujący sposób;Dlaczego otrzymuję ostrzeżenie dla niewyrównanego wskaźnika, ale nie odwołanie?

void FuncA(double &x) 
{ 
    x = 0; 
} 

void FuncB(double *x) 
{ 
    *x = 0; 
} 

#pack(1) 

struct 
{ 
    char c; 
    double x; 
} MyStruct; 

#pack(); 

void MyFunc() 
{ 
    MyStruct M; 
    FuncA(M.x); // This is OK 
    FuncB(&M.x); // This generates a warning C4366 
} 

Podczas kompilacji pod VS2010 SP1 kierowania 64 bit, nazywając FuncB z członkiem wypełnieniem struktury generuje następujące ostrzeżenie;

warning C4366: Wynik jednoargumentowego '&' operatora może być niewyrównany

co następuje wywołanie FuncA nie. Sądziłbym, że oba przypadki zostałyby skompilowane do tego samego kodu. Czy odniesienia są w jakiś sposób bezpieczniejsze z powodu problemów z wyrównaniem niż równoważny wskaźnik, czy też MSVC po prostu nie wydaje ostrzeżenia w miejscu, w którym powinien? Projekt wymaga opakowanie struktura jest utrzymany, więc moje wybory są albo zmienić FuncB do

void FuncB(__unaligned double *x) 
{ 
    *x = 0; 
} 

lub po prostu użyć FuncA we wszystkich takich przypadkach. Ten drugi byłby lepszy, ponieważ jest bardziej przenośny, ale zastanawiam się, czy zadziała, czy też brak ostrzeżenia w przypadku referencji jest po prostu niedogodnością w kompilatorze.

Edytuj: Pomoc Microsoft dla tego błędu to here. Pomoc __unaligned sugeruje, że nieprzestrzeganie tego ostrzeżenia spowoduje wyrzucenie wyjątków na procesorach Itanium. Dalsze trałowania wokół MSDN sugerują there may be issues surrounding unaligned references. Chociaż może to nie powodować problemów dla moich aktualnych użytkowników, jeśli architektura Itanium będzie szerzej stosowana w przyszłości, mogę skonfigurować koszmar wsparcia. Plan polega teraz na dodaniu konkretnych wrapperów dla wszystkich funkcji, które używają spakowanych struktur, aby uniknąć wskaźników i słowa kluczowego __unaligned.

Odpowiedz

7

Odniesienie i wskaźnik to prawie to samo (pod maską, że tak powiem), więc z punktu widzenia bezpieczeństwa nie jest inaczej. Prawdopodobnie jest to raczej niedopatrzenie i/lub że kompilator jest mniej zainteresowany referencjami, ponieważ nie można ich przekazać poza środowiskiem C++ (chociaż jestem skłonny uważać, że jest to po prostu niedopatrzenie).

Możliwe, że kompilator jest bardziej zainteresowany wskaźnikami, ponieważ jest bardziej prawdopodobne, że wskaźniki są używane do wydajności, gdzie chcesz iterować w zakresie wartości double (np. Przydzielając więcej miejsca niż sama struktura używa i przechowywanie kolejnych wartości double) - nie można tego zrobić z odwołaniem. Ponieważ niezaalibrowany dostęp jest co najmniej wolniejszy niż dostęp wyrównany, może to mieć wpływ na wydajność, aw niektórych systemach spowoduje pułapkę systemu operacyjnego, która albo "naprawi" niewyrównany dostęp (w tempie kilku zamówień o wiele wolniej niż zwykły dostęp wyrównany) lub system operacyjny po prostu mówi "Twój program spowodował niewyrównany dostęp, zabijam go".

Występują również problemy z wielowątkowością, ponieważ niealarmowany dostęp może nie być atomowym aktualizowaniem danych. Oczywiście należy użyć wartości std::atomic lub podobnej dla danych udostępnianych między wątkami.

Urządzenie x86 doskonale nadaje się do odczytu double z niezaalokowanego adresu. Myślę, że Itanium nie jest, ale podejrzewam, że nie używasz tego procesora, statystycznie rzecz biorąc. Inne, starsze architektury, takie jak Alpha, mogą mieć problemy z odczytaniem niewyrównanej pamięci.

+3

Niewyrównany dostęp jest wolniejszy niż dostęp wyrównany, aw środowiskach wielowątkowych może mieć inne niepożądane efekty (wyrównany odczyt/zapis w intel jest atomowy, ale nie w przypadku nie wyrównanego dostępu: z dwoma wątkami zapisującymi wartości 1 i 2^31 do tej samej zmiennej i wątku odczytującego wartość, jeśli wartość jest wyrównana, gwarantowane jest odczytanie 1 lub 2^31, przy braku dostępu, który nie ma miejsca). Inne platformy (SPARC) nie mogą obsłużyć niepodpisanych odczytów/zapisów, a procesor będzie przechwytywał pułapkę. –

+0

Mam zaktualizowane "tutaj jest, dlaczego myślę, że to jest ważniejsze dla wskaźników niż referencje", aby wyjaśnić, że brak równego dostępu jest wolniejszy. Nie jestem świadomy żadnej wersji systemu Windows dla SPARC, więc nie sądzę, aby jego zachowanie miało znaczenie, a 64-bitowa technologia ARM nie jest jeszcze dostępna dla systemu Windows. Co pozostawia X86 i Itanium ... –

+0

To był tylko komentarz dotyczący ostrzeżeń kompilatora C++ i niewyrównanego dostępu, ale jeśli chcesz rozważyć alfa zamiast sparc. Było wiele systemów operacyjnych Windows działających w wersji alfa, nie wiem, czy są to nowsze wersje. Odnośnie edycji ... ouch. Odpowiedź była lepsza wcześniej! –

Powiązane problemy