-
11. Data: 2015-12-03 15:05:04
Temat: Re: Pakowanie struktur
Od: Tomasz Kaczanowski <kaczus@dowyciecia_poczta.onet.pl>
W dniu 2015-12-03 15:00, M.M. pisze:
> On Thursday, December 3, 2015 at 2:34:00 PM UTC+1, Tomasz Kaczanowski wrote:
>> W dniu 2015-12-03 14:08, M.M. pisze:
>>> On Thursday, December 3, 2015 at 1:09:14 PM UTC+1, Tomasz Kaczanowski wrote:
>>>
>>>> i gdzieniegdzie będzie mały bum, bo *((int*)(buf+2)); może mieć zdziebko
>>>> inną zawartość, niż nam się wydaje,
>>>
>>> Nie rozumiem. W jakich sytuacjach może mieć inną zawartość? Na moje
>>> albo reprezentacja bitowa się zgadza, albo nie. Jeśli nie, to w
>>> ogóle nie można używać kopiowania bitów.
>>
>> Tam gdzie zmienne muszą mieć wyrównane adresy. O ile w przypadku
>> spakowanej struktury przy odczycie kompilator wykona za nas odpowiednie
>> operacje, to w takim przypadku, gdy rzutujesz dane spod adresu, mówisz
>> kompilatorowi "wiem co robię, nie wtrącaj się", a, że wynik może w takim
>> przypadku być inny, cóż...
>
> To przy operacji:
> *((int*)(buf+2))
> kompilator nie wygeneruje takiego samego kodu jak przy wypakowaniu
> inta przesuniętego o 2 bajty w strukturze? Myślałem że na danej
> platformie kompilator bezpiecznie przerzuci dane na wyrównany adres i
> dopiero potem zacznie operować na tych danych.
z doświadczenia wiem, że nie poprawne było dopiero
int zmienna;
memcpy(zmienna, (buf+2), sizeof(int));
--
Kaczus
http://kaczus.ppa.pl
-
12. Data: 2015-12-03 15:20:26
Temat: Re: Pakowanie struktur
Od: Maciej Sobczak <s...@g...com>
Piszę tutaj, ale problem dotyczy wszystkich postów w tym wątku.
Uwaga 1: endianie atakują.
Te tricki są do niczego i powinny być (i są) zakazane. W szczególności *wszystkie*
pokazane do tej pory przykłady są zakazane przez przemysłowe standardy kodowania -
właśnie dlatego, że działają tylko przypadkiem i to w ściśle określonych warunkach,
których to warunków nie widać w kodzie.
Jak chcecie przepakowywać protokoły sieciowe, to ręcznie (uwaga 2: do operacji na
bitach służą typy unsigned) a nie przez jakieś tam pragma packi czy inne pola bitowe.
Dobrze napisany kod jest przenośny. I czytelny.
--
Maciej Sobczak * http://www.inspirel.com
-
13. Data: 2015-12-03 16:08:39
Temat: Re: Pakowanie struktur
Od: "M.M." <m...@g...com>
On Thursday, December 3, 2015 at 3:05:24 PM UTC+1, Tomasz Kaczanowski wrote:
> W dniu 2015-12-03 15:00, M.M. pisze:
> > On Thursday, December 3, 2015 at 2:34:00 PM UTC+1, Tomasz Kaczanowski wrote:
> >> W dniu 2015-12-03 14:08, M.M. pisze:
> >>> On Thursday, December 3, 2015 at 1:09:14 PM UTC+1, Tomasz Kaczanowski wrote:
> >>>
> >>>> i gdzieniegdzie będzie mały bum, bo *((int*)(buf+2)); może mieć zdziebko
> >>>> inną zawartość, niż nam się wydaje,
> >>>
> >>> Nie rozumiem. W jakich sytuacjach może mieć inną zawartość? Na moje
> >>> albo reprezentacja bitowa się zgadza, albo nie. Jeśli nie, to w
> >>> ogóle nie można używać kopiowania bitów.
> >>
> >> Tam gdzie zmienne muszą mieć wyrównane adresy. O ile w przypadku
> >> spakowanej struktury przy odczycie kompilator wykona za nas odpowiednie
> >> operacje, to w takim przypadku, gdy rzutujesz dane spod adresu, mówisz
> >> kompilatorowi "wiem co robię, nie wtrącaj się", a, że wynik może w takim
> >> przypadku być inny, cóż...
> >
> > To przy operacji:
> > *((int*)(buf+2))
> > kompilator nie wygeneruje takiego samego kodu jak przy wypakowaniu
> > inta przesuniętego o 2 bajty w strukturze? Myślałem że na danej
> > platformie kompilator bezpiecznie przerzuci dane na wyrównany adres i
> > dopiero potem zacznie operować na tych danych.
>
>
> z doświadczenia wiem, że nie poprawne było dopiero
>
> int zmienna;
> memcpy(zmienna, (buf+2), sizeof(int));
Jeśli wcześniej było:
memcpy( buf+2 , &zmienna , sizeof(int) );
To też nie widzę zagrożenia. Rozmawiamy rzecz jasna o zgodnym formacie
na poziomie bitów.
Gdy ktoś upakował dane przy pomocy memcpy, a potem odzyskuje przez:
*((int*)(buf+2))
to obawiam się, że nie zawsze zadziała, o ile się nie mylę, to zadziała
tylko na bigendian.
Pozdrawiam
-
14. Data: 2015-12-03 16:19:26
Temat: Re: Pakowanie struktur
Od: "M.M." <m...@g...com>
On Thursday, December 3, 2015 at 3:20:27 PM UTC+1, Maciej Sobczak wrote:
> Piszę tutaj, ale problem dotyczy wszystkich postów w tym wątku.
>
> Uwaga 1: endianie atakują.
>
> Te tricki są do niczego i powinny być (i są) zakazane.
Jakie triki? W ogóle nie można rozpoznać na podstawie samych
danych w jakim formacie są zakodowane. Rozmawiamy oczywiście o
zgodnych formatach. Jeśli formaty są niezgodne, to trzeba napisać
switch każdej pary (src,dst) formatów.
> W szczególności *wszystkie* pokazane do tej pory przykłady są zakazane
> przez przemysłowe standardy kodowania - właśnie dlatego, że działają tylko
> przypadkiem i to w ściśle określonych warunkach, których to warunków nie
> widać w kodzie.
Działają zawsze na zgodnych formatach.
> Jak chcecie przepakowywać protokoły sieciowe, to ręcznie (uwaga 2: do operacji na
bitach służą typy unsigned) a nie przez jakieś tam pragma packi czy inne pola bitowe.
Dobrze napisany kod jest przenośny. I czytelny.
Gdy są zgodne formaty, to nie trzeba niczego przepakowywać. Wystarczy
odczytać (w tej samej kolejności) i używać.
Pozdrawiam
-
15. Data: 2015-12-03 16:21:30
Temat: Re: Pakowanie struktur
Od: witek <w...@g...pl.invalid>
M.M. wrote:
> Generalnie wtedy kiedy chcemy oszczędzać pamięć
to chyba ostatnie z zastosowań jak się już komuś bardzo nudzi.
-
16. Data: 2015-12-03 16:23:35
Temat: Re: Pakowanie struktur
Od: "M.M." <m...@g...com>
On Thursday, December 3, 2015 at 4:21:31 PM UTC+1, witek wrote:
> M.M. wrote:
> > Generalnie wtedy kiedy chcemy oszczędzać pamięć
>
>
> to chyba ostatnie z zastosowań jak się już komuś bardzo nudzi.
To co innego może zrobić ktoś, komu dane nie mieszczą się w
pamięci?
Pozdrawiam
-
17. Data: 2015-12-03 17:29:01
Temat: Re: Pakowanie struktur
Od: Maciej Sobczak <s...@g...com>
> Jakie triki? W ogóle nie można rozpoznać na podstawie samych
> danych w jakim formacie są zakodowane.
Przecież nikt nie każe rozpoznawać formatu na podstawie danych. O ile zrozumiałem
nawiązanie do protokołów sieciowych, to format jest zwykle znany z góry.
> Rozmawiamy oczywiście o
> zgodnych formatach.
Co to znaczy zgodnych formatach? Jest jeden format (zwykle znany) i trzeba go
zdekodować na poszczególne pola (albo odwrotnie - spakować ze znanych wartości pól).
Te triki z pragmą, polami bitowymi albo rzutowaniem wskaźników to są złe rozwiązania.
--
Maciej Sobczak * http://www.inspirel.com
-
18. Data: 2015-12-03 17:45:14
Temat: Re: Pakowanie struktur
Od: witek <w...@g...pl.invalid>
M.M. wrote:
> On Thursday, December 3, 2015 at 4:21:31 PM UTC+1, witek wrote:
>> M.M. wrote:
>>> Generalnie wtedy kiedy chcemy oszczędzać pamięć
>>
>>
>> to chyba ostatnie z zastosowań jak się już komuś bardzo nudzi.
>
> To co innego może zrobić ktoś, komu dane nie mieszczą się w
> pamięci?
>
zmienic algorytm.
po za tym w jaki sposob wielkosc danych ma sie do faktu do czego stosuje
sie pragma pack?
-
19. Data: 2015-12-03 17:56:00
Temat: Re: Pakowanie struktur
Od: "M.M." <m...@g...com>
On Thursday, December 3, 2015 at 5:29:03 PM UTC+1, Maciej Sobczak wrote:
> > Jakie triki? W ogóle nie można rozpoznać na podstawie samych
> > danych w jakim formacie są zakodowane.
>
> Przecież nikt nie każe rozpoznawać formatu na podstawie danych. O ile zrozumiałem
nawiązanie do protokołów sieciowych, to format jest zwykle znany z góry.
Jeśli przyszły dane w formacie znanym na podstawie protokołu, to trzeba
napisać konwersję zgodną z danym formatem. Rozmowa, w kontekście znanego
protokołu, zarówno o kopiowaniu bit po bicie, jak i o kopiowaniu z
użyciem operatora konwersji (int), nie ma sensu. Rozmawialiśmy o
szczególikach, typu:
1) można się przejechać na big/lit endian
2) najpierw memcpy, potem operator rzutowania
3) różny padding w strukturach
4) różny rozmiar inta na różnych platformach lub wersjach programu.
> > Rozmawiamy oczywiście o
> > zgodnych formatach.
>
> Co to znaczy zgodnych formatach? Jest jeden format (zwykle znany) i trzeba go
zdekodować na poszczególne pola (albo odwrotnie - spakować ze znanych wartości pól).
Te triki z pragmą, polami bitowymi albo rzutowaniem wskaźników to są złe rozwiązania.
Dlaczego złe? Jeśli ktoś wysyła tablicę struktur wyrównanych do 1 bajta, to
sytuacja ma się odwrotnie niż pisałeś: Jedynie przez przypadek odczyt
zadziała na strukturach wyrównanych do 4 bajtów. Dlatego są złe, że nie
używa się przenośnych funkcji do wysłania i odebrania każdego pola? Owszem
to drobna wada. Ale wyobraź sobie, że ktoś pisze program tylko na windows i
tylko na x86, ma strutkurę z 20ma polami i zamiast napisać
write( &strukt , sizeof(strukt) , file )
pisze 20 razy:
write( unwersalny_format_int( strukt.pole1 ) , uniwersalny_rozmiar_int( strukt.pole1
) , file );
Zgodzę się, że kod z memcpy jest ryzykowny, ale po pierwsze ryzyko to pojawia
się tylko w określonych sytuacjach, a aktywne unikanie tego ryzyka zajmuje
czas. Zobacz jak łatwo rypnąć się po poprawce pól w strukturze.
Pozdrawiam
-
20. Data: 2015-12-03 18:02:17
Temat: Re: Pakowanie struktur
Od: "M.M." <m...@g...com>
On Thursday, December 3, 2015 at 5:45:16 PM UTC+1, witek wrote:
> M.M. wrote:
> > On Thursday, December 3, 2015 at 4:21:31 PM UTC+1, witek wrote:
> >> M.M. wrote:
> >>> Generalnie wtedy kiedy chcemy oszczędzać pamięć
> >>
> >>
> >> to chyba ostatnie z zastosowań jak się już komuś bardzo nudzi.
> >
> > To co innego może zrobić ktoś, komu dane nie mieszczą się w
> > pamięci?
> >
>
> zmienic algorytm.
> po za tym w jaki sposob wielkosc danych ma sie do faktu do czego stosuje
> sie pragma pack?
#include <cstdio>
struct X1 {
int c;
char a;
};
#pragma push
#pragma pack(1)
struct X2 {
int c;
char a;
};
#pragma pop
int main(int argc, char *argv[])
{
static X1 x1[1000];
static X2 x2[1000];
printf("sizeof(x1)==%u\n" , (sizeof(x1) ) );
printf("sizeof(x2)==%u\n" , (sizeof(x2) ) );
return 0;
}
U mnie taki wynik:
sizeof(x1)==8000
sizeof(x2)==5000
Pozdrawiam