Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Kod koji daje neočekivani rezultat

[es] :: Art of Programming :: Kod koji daje neočekivani rezultat

Strane: << < .. 2 3 4 5 6 7

[ Pregleda: 53555 | Odgovora: 128 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

Burgos
Nemanja Borić
Amazon Web Services
Berlin

Član broj: 12484
Poruke: 1912
54.239.6.*

Sajt: stackoverflow.com/users/1..


+471 Profil

icon Re: Kod koji daje neočekivani rezultat27.01.2020. u 14:59 - pre 32 dana
Izvinjavam se, C ne dozvoljava anonimne unije u ovom obliku. Evo istog programa koji se kompajlira i sa C i sa C++ kompajlerom. Međutim, u C-u je ovaj program potpuno definisan, dok u C++-u ovaj program sadrži undefined behavior (pristupanje neaktivnog člana unije):

Code:
#include <stdint.h>

float InverseSquareRoot(float x)
{
    union unija
    {
        float as_float;
        int32_t as_int;
    };
    union unija u;
    float xhalf = 0.5f*x;
    u.as_float = x;
    u.as_int = 0x5f3759df - (u.as_int>>1);
    u.as_float = u.as_float*(1.5f - xhalf*u.as_float*u.as_float);
    return u.as_float;
}
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8320
*.dynamic.isp.telekom.rs.



+2689 Profil

icon Re: Kod koji daje neočekivani rezultat27.01.2020. u 15:37 - pre 31 dana i 23h
Možda je u teoriji u C++ jeziku to nedefinisano, ali u praksi radi. Probao sam sa g++ i clang++ kompajlerom i inverzni kvadratni koren se računa ispravno.
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

Burgos
Nemanja Borić
Amazon Web Services
Berlin

Član broj: 12484
Poruke: 1912
54.239.6.*

Sajt: stackoverflow.com/users/1..


+471 Profil

icon Re: Kod koji daje neočekivani rezultat27.01.2020. u 15:58 - pre 31 dana i 23h
"U praksi" je vrlo klimav pojam. Ne postoji garancija da će ovaj program raditi na svim implementacijama, pa ni u narednoj iteraciji GNU C++ kompajlera. Već smo videli takve primere sa strict aliasing, sa std::launder, pa se i na ovo ne sme oslanjati.

Howard Hinnant u SO linku sa koga sam preuzeo ovaj primer kaže:

Citat:
This is due to the compiler's choice to compile it like this. It had been equally valid for the compiler to produce different, broken code.


A evo ga i link ka celoj diskusiji unutar C++ komiteta o ovome (WG21 UB study group): http://www.open-std.org/pipermail/ub/2013-July/000071.html
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8320
*.dynamic.isp.telekom.rs.



+2689 Profil

icon Re: Kod koji daje neočekivani rezultat27.01.2020. u 16:09 - pre 31 dana i 23h
Imaš li ti primer da to ne radi na nekom kompajleru? Zbog čega bi neko kvario kompajler u sledećim verzijama? Vidi, ako ne postoji fundamentalan razlog protiv toga da radi kako se očekuje, svi će tako da naprave kompajler.
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

Burgos
Nemanja Borić
Amazon Web Services
Berlin

Član broj: 12484
Poruke: 1912
54.239.6.*

Sajt: stackoverflow.com/users/1..


+471 Profil

icon Re: Kod koji daje neočekivani rezultat27.01.2020. u 16:41 - pre 31 dana i 22h
Imaš li ti dokaz da radi na svakom kompajleru? Pošto standard, koji definiše šta je C++, a ne kompajleri, za ovaj program kaže da je nedefinisan.

Ovaj kod nije portabilan, za razliku od C verzije koja jeste, u kojoj je ponašanje jasno određeno standardom.

Fundamentalni razlog može da bude vrlo prizeman, kao što je optimizacija, kada kompajler može da vidi da se u samo jedno polje unije upisivalo, i da zameni celu uniju samo jednim poljem, ostavljajući sve ostalo nedefinisano.

Već sam ti dao primere u prošlosti kada je kompajler zbog optimizacije kao fundamentalnog razloga, potpuno razbio neportabilne programe. Najčuveniji je strict-aliasing, koji je razbio mnogo toga, uključujući i Linux kernel. Evo Linusova poruka na tu temu (https://lkml.org/lkml/2003/2/26/158, boldovanje moje):


Citat:

Why do you think the kernel uses "-fno-strict-aliasing"?

The gcc people are more interested in trying to find out what can be
allowed by the c99 specs than about making things actually _work_.
The
aliasing code in particular is not even worth enabling, it's just not
possible to sanely tell gcc when some things can alias.


> Some users have complained that when the following code is
>compiled without the -fno-strict-aliasing, the order of the write and
>memcpy is inverted (which mean a bogus len is mem-copied into the
>stream).

The "problem" is that we inline the memcpy(), at which point gcc won't
care about the fact that it can alias, so they'll just re-order
everything and claim it's out own fault. Even though there is no sane
way for us to even tell gcc about it.

I tried to get a sane way a few years ago, and the gcc developers really
didn't care about the real world in this area.
I'd be surprised if that
had changed, judging by the replies I have already seen.

I'm not going to bother to fight it.



https://www.mail-archive.com/[email protected]/msg01647.html

Citat:
That's INSANE. It's so incredibly insane that people who do that should
just be put out of their misery before they can reproduce. But real gcc
developers really thought that it makes sense, because the standard allows
it, and it gives the compiler the maximal freedom - because it can now do
things that are CLEARLY NONSENSICAL.

And to compiler people, being able to do things that are clearly
nonsensical seems to often be seen as a really good thing, because it
means that they no longer have to worry about whether the end result works
or not - they just got permission to do stupid things in the name of
optimization.


So gcc did. I know for a _fact_ that gcc would re-order write accesses
that were clearly to (statically) the same address. Gcc would suddenly
think that

unsigned long a;

a = 5;
*(unsigned short *)&a = 4;

could be re-ordered to set it to 4 first (because clearly they don't alias
- by reading the standard), and then because now the assignment of 'a=5'
was later, the assignment of 4 could be elided entirely! And if somebody
complains that the compiler is insane, the compiler people would say
"nyaah, nyaah, the standards people said we can do this", with absolutely
no introspection to ask whether it made any SENSE.



Još nekoliko primera, kao što su https://davmac.wordpress.com/2009/10/ možeš naći na https://stackoverflow.com/ques...ct-aliasing-and-horror-stories

Ne mogu da pronađem tačno kada je GCC podrazumevano uključio strict aliasing, ali https://www.gnu.org/software/gcc/bugs/ kaže "recently":

Citat:
Recent versions of GCC turn on the option -fstrict-aliasing (which allows alias-based optimizations) by default with -O2. And some architectures then really print "1111 1111" as result. Without optimization the executable will generate the "expected" output "2222 2222".

 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8320
*.dynamic.isp.telekom.rs.



+2689 Profil

icon Re: Kod koji daje neočekivani rezultat27.01.2020. u 17:15 - pre 31 dana i 21h
Govorimo o primeru programskog koda koji se kompajlira C kompajlerom, C je portabilan, C++ neportabilan u praksi. Ti ga nisi naveo. Navodiš neke primer koda koji nije C portabilan, što nije tema.

Ja tvrdim da toga nema jer ne postoji razlog za to.

Autore C++ standarda je blam da napišu da se unije koje se kompajliraju C kompajlerom, kompajliraju C++ kompajlerom na isti način, već hoće da formulišu opštu OOP teoriju o uslovima kompajliranja unija, pa to ne uspevaju u celini. Posledica toga je da ono što piše u C++ standardu ne obuhvata sve slučajeve koji su obuhvaćeni C standardom.

Sa druge strane, autori kompajlera itekako razlikuju tipovi koji suštinski nemaju veze sa OOP-om (trivijalni podrazumevani konstruktor, konstruktor kopije, pomerajući konstruktor kopije, destruktor, operator dodele, pomerajući operator dodele, operatori poređenja) zbog optimizacije. Posledica toga je da se svi takvi tipovi koji, koji obuhvataju sve C-ovske tipove (struktura koja ništa ne nasleđuje i nijedna metoda nije navedena je obuhvaćena time) kompajliraju na isti način kao u C-u.
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8320
*.mediaworksit.net.



+2689 Profil

icon Re: Kod koji daje neočekivani rezultat28.01.2020. u 17:58 - pre 30 dana i 21h
Da li neko zna odgovor na pitanje postavljeno ovde

https://www.elitesecurity.org/p3932749
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

Burgos
Nemanja Borić
Amazon Web Services
Berlin

Član broj: 12484
Poruke: 1912
54.239.6.*

Sajt: stackoverflow.com/users/1..


+471 Profil

icon Re: Kod koji daje neočekivani rezultat29.01.2020. u 09:01 - pre 30 dana i 6h
Pre nego što operativni sistem da procesu stranice memorije, uvek se izvrši brisanje vrednosti (zapravo, drugačije, neki operativni sistemi to rade na živo pre slanja programu http://lists.dragonflybsd.org/...ommits/2016-August/624202.html, neki uvek dodeljuju 0 stranicu i pomoću CoW daju novu u slučaju da pišeš u nju). U suprotnom, tvoj program bi mogao da dobije stranicu memorije sa šiframa iz Chromiuma, ili slično..

[Ovu poruku je menjao Burgos dana 29.01.2020. u 10:35 GMT+1]

-- EDIT: greške u kucanju.

[Ovu poruku je menjao Burgos dana 29.01.2020. u 10:36 GMT+1]
 
Odgovor na temu

Nedeljko
Nedeljko Stefanović

Član broj: 314
Poruke: 8320
*.mediaworksit.net.



+2689 Profil

icon Re: Kod koji daje neočekivani rezultat29.01.2020. u 10:53 - pre 30 dana i 4h
Da, tako je.

Pre nego što se blok osnlobođen od nekog procesa dodeli nekom drugom procesu, on mora biti popunjennulama iz sigurnosnih razloga.
Nije bitno koji su zaključci izvučeni, već kako se do njih došlo.
 
Odgovor na temu

[es] :: Art of Programming :: Kod koji daje neočekivani rezultat

Strane: << < .. 2 3 4 5 6 7

[ Pregleda: 53555 | Odgovora: 128 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.