Je jazyk C skutočne ťažký?

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #180 kdy: 11. 06. 2025, 13:11:40 »
Kód: [Vybrat]
uint32_t *p_u32 = 0x00000040;
*p_u32 = 0x12345678; // zapiš hodnotu 0x12345678 na adresu 0x00000040

Toto je naprosto legitimní C-kód, sic platform specific.

To není tak úplně pravda. Tohle je legální jen s "volatile". Jinak bude optimalizátor provádět psí kusy.
Jasně, může. Ale o to mi zrovna nešlo. Šlo mi o to že v C je standard zapisovat přes pointer na paměťové adresy, nebo z nich číst. To že to může vyvolat něco co nechci, v závislosti na runtime environmentu je až druhotná věc.

Tady jsem ze srandy přeložil kód pro různé platformy, různými překladači a všechny zapíší na adresu 0x40 4 bajty s hodnotou 0x12 0x34 0x56 0x78. Takže jaképak jenom GCC, jakýpak nestandard?

Mimochodem, nepoužil jsem volatile, i když s ním je to jistota - to souhlas.

Kód: [Vybrat]
--- arm7 clang
f:
        ldr     r0, .LCPI0_0
        mov     r1, #64
        str     r0, [r1]
        bx      lr
.LCPI0_0:
        .long   305419896

--- gcc
f():
        mov     DWORD PTR ds:64, 305419896
        ret

--- djgpp
__Z1fv:
        mov     DWORD PTR ds:64, 305419896
        ret

--- icc
f:
..B1.1:                         # Preds ..B1.0
        mov       DWORD PTR [64], 305419896                     #6.6
        ret                                                     #7.1

--- avr-gcc
f:
.L__stack_usage = 0
        ldi r24,lo8(120)
        ldi r25,lo8(86)
        ldi r26,lo8(52)
        ldi r27,lo8(18)
        out 0x20,r24
        out 0x21,r25
        out 0x22,r26
        out 0x23,r27
        ret


vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #181 kdy: 11. 06. 2025, 13:20:06 »
To nema s GCC nic společného. Takhle se psalo jestě než nějaký GCC vůbec existoval. A ani to nemá nutně nic společného s adresou 0. Prostě obecně když mám pointer a přectu přes něj nebo zapíšu, tak čtu nebo zapisuju z nějaké adresy v paměti která odpovídá hodnotě pointeru. Tady nic nestandardního není.
Pořád tomu nerozumíš. Nevadí, zkusím to vysvětlit znovu. null pointer (adresa 0) se v C standardu ošetřuje speciálně. C standard explicitně říká, že dereference null pointeru je undefined behavior. Tozn. pokud máš v C programu čtení nebo zápis adresy 0, překladač s tím může udělat cokoliv (a taky dělá). Může to ignorovat, může vygenerovat neplatnou instrukci, může to dokonce i fyzicky provést. Jakékoliv chování, včetně všech zmíněných, je při dereferenci null pointeru legální.

Já tomu rozumím a chápu to. Já jenom nechápu co s tím máš za problém. Prostě si překladač nastavím jak potřebuju. Když píšu driver nebo knihovnu pro MCU kde tam potřebuju opravdu zapsat, tak si to tak nastavím. Když píšu program běžící v rámci OS tak to samozřejmě nechám generovat ud2 instrukci abych to odchytil v debuggeru. To že přes pointer se dá zapisovat na adresu a že toto je platné v C všude stále platí. Hodnota 0 může být speciálně handlovaná překladačem, ale to je optional. Tak samo ale může být potřeba vytvořit program který to cíleně dělá a překladač by to měl umožnit (alespoň nějakým přepínačem jako to má GCC).

Re:Je jazyk C skutočne ťažký?
« Odpověď #182 kdy: 11. 06. 2025, 13:34:11 »
Prostě si překladač nastavím jak potřebuju.
Můžeš prohlásit, že dereference pointeru není undefined behavior. Můžeš i zkusit donutit překladač, aby při dereferenci null pointeru dělal něco definovaného. Nemáš pak ale validní C program. Máš program, který je dle C standardu nefunkční, standard říká, že nedefinuje jeho chování.

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #183 kdy: 11. 06. 2025, 13:41:09 »
Prostě si překladač nastavím jak potřebuju.
Můžeš prohlásit, že dereference pointeru není undefined behavior. Můžeš i zkusit donutit překladač, aby při dereferenci null pointeru dělal něco definovaného. Nemáš pak ale validní C program. Máš program, který je dle C standardu nefunkční, standard říká, že nedefinuje jeho chování.

To mě ale nezajímá, mě zajíma jaký bude strojový kód a co program dělá a jestli dělá to co chci.

Re:Je jazyk C skutočne ťažký?
« Odpověď #184 kdy: 11. 06. 2025, 13:43:10 »
To mě ale nezajímá, mě zajíma jaký bude strojový kód a co program dělá a jestli dělá to co chci.
V pořádku, ale neříkej potom, že píšeš v C. Nepíšeš totiž v C, ale v nějakém vrid dialektu, kdy jsou tvoje programy funkční jen s konkrétním nastavením překladače na konkrétní platformě.


vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #185 kdy: 11. 06. 2025, 13:49:21 »
To mě ale nezajímá, mě zajíma jaký bude strojový kód a co program dělá a jestli dělá to co chci.
V pořádku, ale neříkej potom, že píšeš v C. Nepíšeš totiž v C, ale v nějakém vrid dialektu, kdy jsou tvoje programy funkční jen s konkrétním nastavením překladače na konkrétní platformě.

Píšu v C. Kde mám platform/compiler specific věci, tak použiju #ifdef a do poslední #else větve dám error "not implemented" a nechám toho kdo to někdy bude v budoucnu potřebovat, aby ty #else větve dopsal. Nebudu paralyzovat celý vývoj jenom kvůli tomu abych všem linuxákům vyhověl. Za to mě zákazník neplatí.

Re:Je jazyk C skutočne ťažký?
« Odpověď #186 kdy: 11. 06. 2025, 13:55:46 »
Píšu v C. Kde mám platform/compiler specific věci, tak použiju #ifdef a do poslední #else větve dám error "not implemented" a nechám toho kdo to někdy bude v budoucnu potřebovat, aby ty #else větve dopsal. Nebudu paralyzovat celý vývoj jenom kvůli tomu abych všem linuxákům vyhověl. Za to mě zákazník neplatí.
Nepíšeš v C. Ve chvíli, kdy uděláš dereferenci null pointeru nebo jiné undefined behavior, tak od toho C standard dává ruce pryč. Na některých platformách takové věci můžou dávat smysl, ale vždy musíš explicitně zdůraznit, že se jedná o platformově závislou věc, kterou musíš speciálně řešit, např. nějakými flagy překladače. Ty to tady prezentuješ jako něco normálního, ale děláš je pravý opak, pohybuješ se mimo C stadard a musíš to záplatovat nějakými ohýbáky.

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #187 kdy: 11. 06. 2025, 14:06:27 »
Píšu v C. Kde mám platform/compiler specific věci, tak použiju #ifdef a do poslední #else větve dám error "not implemented" a nechám toho kdo to někdy bude v budoucnu potřebovat, aby ty #else větve dopsal. Nebudu paralyzovat celý vývoj jenom kvůli tomu abych všem linuxákům vyhověl. Za to mě zákazník neplatí.
Nepíšeš v C. Ve chvíli, kdy uděláš dereferenci null pointeru nebo jiné undefined behavior, tak od toho C standard dává ruce pryč. Na některých platformách takové věci můžou dávat smysl, ale vždy musíš explicitně zdůraznit, že se jedná o platformově závislou věc, kterou musíš speciálně řešit, např. nějakými flagy překladače. Ty to tady prezentuješ jako něco normálního, ale děláš je pravý opak, pohybuješ se mimo C stadard a musíš to záplatovat nějakými ohýbáky.

Nesmysl. Zápis přes pointer na adresu v paměti je naprosto standardní věc v C. To jenom ty zase musíš vytahovat nějaké speciality jako adresa 0 abys ukázal že jsi věčný troublemaker. Good job :D

Re:Je jazyk C skutočne ťažký?
« Odpověď #188 kdy: 11. 06. 2025, 14:13:32 »

Ono existuje? UB se přece nikdy neděje. Ty jako programátor ses o to přece postaral a překladač ti v tom bezmezně věří.  8)

Občas mám pocit, že samotná slova jako "chování", "způsobuje" a podobné zastírají podstatu UB a proč je to občas takový mindfuck. Ta představa, že to UB něco dělá, je svým způsobem strašně špatně.

To už celkom preháňate, nemyslíte? Alebo je to tak, že by ste si to mali do študovať?
Proč přeháním? UB stojí na tom, že nesmí nastat. Validní C programy neobsahují UB. Programátor má za úkol zajistit aby k němu nemohlo dojít.

> Ono existuje?

Aha, takže tu na viac ako stovke príspevkov komunikujeme o niečom, čo neexistuje? To je naozaj zvláštne. UB je jednoducho formálny koncept a ako taký celkom určite existuje. Je to zjednodušujúci pojem používaný v odbornej komunikácii na popis toho, čo sa deje v programe, keď je jeho zdrojový kód mimo rámec definovaný sémantikou jazyka.

> UB se přece nikdy neděje.

Skúste vo svojej úvahe použiť definíciu nedefinovaného správania tak ako bola pôvodne myslená.

> Občas mám pocit, že samotná slova jako "chování", "způsobuje" a podobné zastírají podstatu UB

Ten pojem sa vám môže nepáčiť, môžete proti tomu protestovať, ale to je asi tak všetko, čo s tým môžete robiť. Odborná komunita sa jednoducho pred desiatkami rokov zhodla na tom, že sa tento pojem bude používať a tak sa používa. Paradoxne väčšina ľudí nechce v komunikácii uvádzať úplnú výstižnú definíciu a radšej používa zaužívaný zjednodušujúci pojem.

Mne osobne sa tiež nepáči slovo vlákno, ale chápem, že je ten pojem zaužívaný.

> mindfuck

??

Re:Je jazyk C skutočne ťažký?
« Odpověď #189 kdy: 11. 06. 2025, 14:18:41 »
Zápis přes pointer na adresu v paměti je naprosto standardní věc v C. To jenom ty zase musíš vytahovat nějaké speciality jako adresa 0 abys ukázal že jsi věčný troublemaker. Good job :D
Já jen cituji C standard, kde je explicitně uvedeno, že dereference null pointeru je undefined behavior. Rozumím tomu, že C standard nemáš přečtený a nevíš to. Nerozumím ale tomu, proč si pořád v opozici a snažíš se tvrdit, že zápis na jakoukoliv adresu přes pointer je v pohodě? Není to v pohodě, zápis na adresu 0 je dle C standardu undefined behavior. Ve chvíli, kdy to uděláš, tak od toho C standard dává ruce pryč a takový program může dělat cokoliv.

Re:Je jazyk C skutočne ťažký?
« Odpověď #190 kdy: 11. 06. 2025, 14:34:31 »
> Ono existuje?

Aha, takže tu na viac ako stovke príspevkov komunikujeme o niečom, čo neexistuje? To je naozaj zvláštne. UB je jednoducho formálny koncept a ako taký celkom určite existuje. Je to zjednodušujúci pojem používaný v odbornej komunikácii na popis toho, čo sa deje v programe, keď je jeho zdrojový kód mimo rámec definovaný sémantikou jazyka.

> UB se přece nikdy neděje.

Skúste vo svojej úvahe použiť definíciu nedefinovaného správania tak ako bola pôvodne myslená.

> Občas mám pocit, že samotná slova jako "chování", "způsobuje" a podobné zastírají podstatu UB

Ten pojem sa vám môže nepáčiť, môžete proti tomu protestovať, ale to je asi tak všetko, čo s tým môžete robiť. Odborná komunita sa jednoducho pred desiatkami rokov zhodla na tom, že sa tento pojem bude používať a tak sa používa. Paradoxne väčšina ľudí nechce v komunikácii uvádzať úplnú výstižnú definíciu a radšej používa zaužívaný zjednodušujúci pojem.

Mne osobne sa tiež nepáči slovo vlákno, ale chápem, že je ten pojem zaužívaný.
Jo, vyjádřil jsem se asi dost nešikovně. Chtěl jsem zdůraznit že zákeřnost UB je v tom, že to není jen nějaká implementačně závislá akce, která se provede místo toho UB.

Že UB znamená, že tahle situace ve validním programu nesmí nastat. A překladač na tom staví a propaguje to i na okolní kód. Takže vygenerovaný kód s tímhle stavem vůbec nepočítá a můžou se dít fakt divné věci.

Citace
> mindfuck

??
Zažil jsem fakt divoké věci. Co se dělo vůbec nepřipomínalo zdroják a navíc to divné chování nebylo vůbec omezení na místo toho UB.

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #191 kdy: 11. 06. 2025, 14:37:33 »
Zápis přes pointer na adresu v paměti je naprosto standardní věc v C. To jenom ty zase musíš vytahovat nějaké speciality jako adresa 0 abys ukázal že jsi věčný troublemaker. Good job :D
Já jen cituji C standard, kde je explicitně uvedeno, že dereference null pointeru je undefined behavior. Rozumím tomu, že C standard nemáš přečtený a nevíš to. Nerozumím ale tomu, proč si pořád v opozici a snažíš se tvrdit, že zápis na jakoukoliv adresu přes pointer je v pohodě? Není to v pohodě, zápis na adresu 0 je dle C standardu undefined behavior. Ve chvíli, kdy to uděláš, tak od toho C standard dává ruce pryč a takový program může dělat cokoliv.

Já když říkám že píšu v C, tak mluvím o syntaxi jazyka. Že ty v tom vidíš standard a nedokázal bys napsat driver který musí zapsat na adresu 0 protože bys měl panickou hrůzu že to je undefined behaviour, to je tvoje mínus. Já jsem pragmatik a flexi. Kde to jde tak píšu portabilní kód, kde to nejde tak platform specific. A jestli tomu říkáš že nepíšu v C, tak si tomu tak říkej, je mě to celkem šumák. Asi vlastně nemám dále co bych tady k diskuzi přispěl, jsem diskvalifikován se o C vůbec bavit, protože dělám embedded věci. Oukej.

Re:Je jazyk C skutočne ťažký?
« Odpověď #192 kdy: 11. 06. 2025, 14:50:34 »
Já když říkám že píšu v C, tak mluvím o syntaxi jazyka. Že ty v tom vidíš standard a nedokázal bys napsat driver který musí zapsat na adresu 0 protože bys měl panickou hrůzu že to je undefined behaviour, to je tvoje mínus. Já jsem pragmatik a flexi. Kde to jde tak píšu portabilní kód, kde to nejde tak platform specific. A jestli tomu říkáš že nepíšu v C, tak si tomu tak říkej, je mě to celkem šumák. Asi vlastně nemám dále co bych tady k diskuzi přispěl, jsem diskvalifikován se o C vůbec bavit, protože dělám embedded věci. Oukej.
Ale to se týká i embedded. I v embedded musíš řešit, že je dereference null pointeru undefined behavior. Dám ti praktický příklad. Jsou mikrokontroléry, které mají RAM v paměťové mapě od adresy 0, takže adresa 0 je naprosto validní pointer do RAM. Co s tím? Vyřeší se to tak, že se RAM zadefinuje od adresy 1 a adresa 0 se ignoruje, abychom se vyhnuli problémům s dereferencí null pointeru. Přijdeme o jeden bajt RAM na mikrokontroléru, ale to je nízká cena za vyřešení problémů s adresou 0 a undefined behavior.

vrit

Re:Je jazyk C skutočne ťažký?
« Odpověď #193 kdy: 11. 06. 2025, 15:06:01 »
Já když říkám že píšu v C, tak mluvím o syntaxi jazyka. Že ty v tom vidíš standard a nedokázal bys napsat driver který musí zapsat na adresu 0 protože bys měl panickou hrůzu že to je undefined behaviour, to je tvoje mínus. Já jsem pragmatik a flexi. Kde to jde tak píšu portabilní kód, kde to nejde tak platform specific. A jestli tomu říkáš že nepíšu v C, tak si tomu tak říkej, je mě to celkem šumák. Asi vlastně nemám dále co bych tady k diskuzi přispěl, jsem diskvalifikován se o C vůbec bavit, protože dělám embedded věci. Oukej.
Ale to se týká i embedded. I v embedded musíš řešit, že je dereference null pointeru undefined behavior. Dám ti praktický příklad. Jsou mikrokontroléry, které mají RAM v paměťové mapě od adresy 0, takže adresa 0 je naprosto validní pointer do RAM. Co s tím? Vyřeší se to tak, že se RAM zadefinuje od adresy 1 a adresa 0 se ignoruje, abychom se vyhnuli problémům s dereferencí null pointeru. Přijdeme o jeden bajt RAM na mikrokontroléru, ale to je nízká cena za vyřešení problémů s adresou 0 a undefined behavior.

Jenže na té adrese může být registr která má nenahraditelnou speciální funkci či význam. To je naprostý nesmysl to řešit tak jak říkáš. To může udělat jenom teoretik který k tomu prakticky nikdy nečmuch.

Normálně se otestuje překladač zda to podporuje a když ne, tak se vybere jiný. Takhle se to v praxi řeší.
Případně se použije inline assembler.

Těžko očekávat že nejaký kód handlující absolutní adresy registrů se bude někam přenášet. Proto je undefined behaviour úplně jedno.
« Poslední změna: 11. 06. 2025, 15:08:35 od vrit »

Re:Je jazyk C skutočne ťažký?
« Odpověď #194 kdy: 11. 06. 2025, 15:36:35 »
Jenže na té adrese může být registr která má nenahraditelnou speciální funkci či význam. To je naprostý nesmysl to řešit tak jak říkáš. To může udělat jenom teoretik který k tomu prakticky nikdy nečmuch.
To je velmi neobvyklé, že by byl speciální registr nějakého mikrokontroléru na adrese 0, kdy jsi na to prakticky narazil a musel jsi to řešit? Neříkam, že neexistují architektury, kde to tak je, ale zajímalo by mě, kde jsi to prakticky potkal? Pokud se totiž něco takového stane, máš opravdu problém. Buď musíš do assembleru a provést zápis tam, nebo dělat v C něco hodně nestandarního a doufat, že se to nerozbije s novou verzí překladače.