Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

użycie pragma pack

Ostatnio zmodyfikowano 2024-03-25 13:51
Autor Wiadomość
nanoant20
Temat założony przez niniejszego użytkownika
użycie pragma pack
» 2024-03-24 10:24:10
dostaje warning: padding struct 'Car' with 4 bytes to align 'carPrice'
poczytałem i załatałem w ten sposób:

C/C++
#pragma pack(push)
#pragma pack(4)  
// dla Wyrownania struktury
struct Car
{
   
string carMake;
   
string carModel;
   
int yearModel;
   
double carPrice;
};
#pragma pack(pop)

działa, ale czy dobrze dobrałem odpowiednią wartość ?
czy może argument powinien przyjąć wartość 8 ?

następna rzecz to mam klasę :

C/C++
class Vehicle
{
private:
   
string make;
   
string model;
   
int year;
   
double price;
   
vector < Vehicle > vehicles;
public:
};

tutaj dostaje 2 worning
1. warning: padding class 'Vehicle' with 4 bytes to align 'price'

2. warning: field vehicles within 'Vehicle' is less aligned than 'vector<Vehicle>' and is usually due to 'Vehicle' being packed, which can lead to unaligned accesses

jak prawidłowo użyć dyrektywy preprocesora #pragma
tego 2 worning'u w ogóle nie rozumiem

testowane na:
system linux Debian 12.5 64bit:
int ma rozmiar 4 bajty.
double ma rozmiar 8 bajty.
string ma rozmiar 32 bajty
P-180955
DejaVu
» 2024-03-24 10:26:39
ChatGPT 4:
Wybór wartości dla dyrektywy `#pragma pack` zależy od tego, jak chcesz, aby Twoje struktury danych były wyrównane w pamięci. Ostrzeżenie, które otrzymujesz, wskazuje na to, że kompilator musiał dodać dodatkowe bajty wyrównania, aby zapewnić, że pole `carPrice` w strukturze `Car` jest odpowiednio wyrównane do granicy, która jest wymagana przez typ `double`.

### Rozmiar wyrównania

- Jeśli ustawisz `#pragma pack(4)`, oznacza to, że największy rozmiar wyrównania dla każdego pola w strukturze to 4 bajty. W przypadku typu `double`, który zwykle wymaga 8-bajtowego wyrównania, może to nie być odpowiednie, ponieważ `double` ma być wyrównany do 8 bajtów na platformach 64-bitowych, aby zapewnić optymalną wydajność dostępu.
- Jeżeli ustawisz `#pragma pack(8)`, wtedy będziesz mieć wyrównanie zgodne z wymaganiami dla typu `double`, co powinno eliminować potrzebę dodawania bajtów wyrównania przed `carPrice`.

W Twoim przypadku, ponieważ `double` wymaga 8 bajtów wyrównania dla optymalnego dostępu na platformie 64-bitowej, prawidłowym wyborem byłoby użycie `#pragma pack(8)`.

### Ostrzeżenia dla klasy `Vehicle`

1. **Ostrzeżenie o wyrównaniu dla `price`**: Podobnie jak w przypadku struktury `Car`, to ostrzeżenie pojawia się, ponieważ pole `price` typu `double` wymaga 8-bajtowego wyrównania. Użycie `#pragma pack(8)` powinno również tutaj pomóc.
   
2. **Ostrzeżenie o mniejszym wyrównaniu dla `vehicles`**: To ostrzeżenie jest bardziej skomplikowane. Wskazuje ono na potencjalny problem z wyrównaniem pola `vehicles`, które jest typu `vector<Vehicle>`. Vektory wymagają specyficznego wyrównania, a użycie dyrektywy `#pragma pack` na klasie, która zawiera `vector`, może naruszać te wymagania, prowadząc do nieoptymalnych dostępów do pamięci lub, w najgorszym przypadku, do błędów wykonania. W związku z tym, generalnie nie zaleca się stosowania `#pragma pack` do klas lub struktur zawierających złożone typy danych, takie jak STL kontenery.

### Rozwiązania

- W przypadku prostych struktur, gdzie wydajność dostępu do pamięci jest krytyczna i jasno znasz wymagania dotyczące wyrównania, używanie `#pragma pack` może być uzasadnione. Jednak należy to robić z rozwagą, mając na uwadze wymagania dotyczące wyrównania wszystkich typów danych w strukturze.
- Dla klas zawierających STL kontenery lub inne złożone typy, lepiej jest unikać używania `#pragma pack`, ponieważ może to prowadzić do problemów z wyrównaniem i wydajnością.

Zamiast stosować `#pragma pack`, zaleca się projektować klasy i struktury w taki sposób, aby naturalnie zapewniać odpowiednie wyrównanie, np. poprzez umieszczanie pól wymagających większego wyrównania na początku struktury lub klasy.
P-180956
nanoant20
Temat założony przez niniejszego użytkownika
» 2024-03-24 10:33:58
czyli podsumowując dla samej struktury mogę użyć dyrektywy `#pragma` tylko zmienić jej argument na `#pragma pack(8)` a jeżeli o klasę to ją przebudować eh.
@DejaVu Dziękuję.
P-180957
DejaVu
» 2024-03-24 10:43:08
W zasadzie to ostatnia linijka jest kluczowa dla Ciebie tj. nie używaj #pragma pack w ogóle, bo nie masz projektu, który by tego wymagał. Kod powinien być maksymalnie prosty. Wydajność w typowych aplikacjach i grach poprawiasz lepszym algorytmem lub nieprocesowaniem tych samych danych wielokrotnie jeżeli da się tego nie robić, a nie mikro-optymalizacjami, które zaciemniają kod. Tak więc dopóki nie robisz sterowników pod konkretny hardware lub nie masz farmy serwerów na którym to samo oprogramowanie jest hostowane, to nie powinieneś w ogóle stosować #pragma pack w swoim kodzie.
P-180958
nanoant20
Temat założony przez niniejszego użytkownika
» 2024-03-24 19:04:18
W zasadzie to ostatnia linijka jest kluczowa dla Ciebie
dokładnie dostosowałem kod do zalecenia:
Zamiast stosować `#pragma pack`, zaleca się projektować klasy i struktury w taki sposób, aby naturalnie zapewniać odpowiednie wyrównanie, np. poprzez umieszczanie pól wymagających większego wyrównania na początku struktury lub klasy.
okroiłem i przebudowałem program do minimalnej formy, ale worning był dalej.
Przeniosłem na inną maszynę z "Debian 11" i o dziwo skompilował się bez żadnych ostrzeżeń
usunąłem "debian 12.5" i zainstalowałem "Windows 10" program się skompilował bez żadnych worning'ów pod g++ jak i Visual Stuido 2th22 z MSVC. w wersji: 1938 199711
 
P-180959
pekfos
» 2024-03-24 23:04:36
Wyłącz ten warning po prostu. Nie należy do typowego zestawu więc pewnie masz gdzieś dodane -Wpadded do opcji kompilatora. #pragma pack jest błędną reakcją na taki komunikat.
P-180960
nanoant20
Temat założony przez niniejszego użytkownika
» 2024-03-25 08:41:14
Wyłącz ten warning po prostu.

dodałem "-Wno-padded" i zadziałało
@pekfos Dziękuje

P-180961
« 1 »
  Strona 1 z 1