Gå til innhold

C++-skaperen er bekymret for framtiden til språket


Anbefalte innlegg

Videoannonse
Annonse
Gjest Slettet+5132

C/C++ er og har alltid vært en katastrofe.

 

https://www.radford.edu/ibarland/Manifestoes/whyC++isBad.shtml

 

Er dessverre ikke mulig å kaste all C-kode umiddelbart, men om 20 år tror jeg C/C++ vil betraktes omtrent som vi betrakter COBOL og FORTRAN i dag - håpløst gammeldags men noe vi må slite med i mange år ennå.

 

La oss se litt på hva han skriver. For det første føler jeg at jeg må presisere at C++ har store svakheter, men hvis du vil skrive programmer med høye krav til ytelse, er C++ en av de få alternativene der ute, og C++ har ganske mange egenskaper som gjør det mer egnet til å skrive store programmer enn Fortran eller C (her er det sikkert mange som er uenige... :p )

 

 

 

 

Yet this is exactly what happens in many computer languages. In C/C++, the programmer (boss) can write "house"[-1] * 37. It's not clear what was intended, but clearly some mistake has been made. It would certainly be possible for the language (the worker) to report it, but what does C/C++ do?

 

Dette kan du få ganske gode feilmeldinger på hvis du bruker en std::vector og .at-funksjonen. Betrakt følgende program: 

#include <iostream>
#include <vector>
int main() {
  std::vector<int> v = {1,2,3,4};
  std::cout << v.at(-10) << std::endl;
}

som gir følgende feilmelding kompilert ved g++ (og clang++)

$ g++ test.cpp -O3 -o test
$ ./test
terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check: __n (which is 18446744073709551606) >= this->size() (which is 4)
Aborted (core dumped)
 

Dette er vel omtrent samme nivå som hva Java vil gi tilbake av feilmelding, utenom kanskje stacktrace.

 

Dette er et resultat av at []-operatoren på vektorer/arrays skal ha NULL ytelsesoverhead, og da er dette den eneste løsningen. Feil av denne typen kan derimot oppdages med statisk kodeanalyse og forskjellige sanatizere ala valgrind og clang. Java gir deg vel også først en feilmelding når du kjører et slikt program. 

 

 

 

A language for students should flag advanced or ambiguous constructs as probable typos. For instance, it's not obvious that in i = v[i++], the final value of i is undefined [C++ ARM, p.46]. It's not difficult for a language to warn you if you write this, but no C++ compilers choose to.

 

Feil, g++ 8.1.1 gir iallfall advarsel om denne oppførselen med -Wall:

// kompiler med
// g++ -Wall
#include <iostream>
#include <vector>
int main() {
    std::vector<int> v = {1,2,3,4};
    int i =0;
    i = v[i++];
    std::cout << i << std::endl;
}
$ g++ test.cpp -Wall
test.cpp: In function ‘int main()’:
test.cpp:6:5: warning: operation on ‘i’ may be undefined [-Wsequence-point]
   i = v[i++];

 

Similarly, an example from the Java Langauge Specification p. 308: “it is not correct that 4.0*x*0.5 [is the same as] 2.0*x; while roundoff happens not to be an issue here, there are large values of x for which the first expression produces infinity (because of overflow) but the second expression produces a finite result.” (Again, the Java spec at least defines what the answer should be in all cases, unlike C++ where this is left to vary between platforms.)

 

Joda, men dette er den tradeoffen en må akseptere hvis C++ skal kunne ha sjans til å oppnå maks ytelse på forskjellige CPUer. Du finner nok ikke noe språk som får begge deler.

 

 

But such programming (and intensive debugging) is not the best place for the effort of an astronomer or medical researchers. Myself, I rarely or never run those types of programs; most of my time waiting on the computer is waiting for a page to download, not a slow program.

 

Nå trenger ofte astronomer ganske høy regneytelse, og de bruker faktisk i stor grad C++ eller Fortran allerede.

Endret av Slettet+5132
Lenke til kommentar

Folk er forskjellige. Noen er bare ikke skapt for lavnivåspråk. Det gjør ikke språkene dårlige.
 
C/C++ er er imidlertid dårlige lavnivåspråk fordi de lar endel ting være udefinerte, i steden for å definere dem til å fungere på den måten som er naturlig for plattformen. Dette skaper problemer når kompilatorer over-optimaliserer
 

In C/C++, the programmer (boss) can write "house"[-1] * 37. It's not clear what was intended, but clearly some mistake has been made.

Eeehhh, nei, hvorfor tror han at det er en feil?? Det gir ingen mening å påstå. Det er ikke en feil hvis house er en peker til midt inni en array.
(Det er mulig C++ har definert det til udefinert, men det er ikke en del av negative indeksers natur. Da har han rett i at C++ er et dårlig språk, men han bommer på hvorfor.)
 

A Bad Choice For Students; An Alternative

Ingen har noen gang påstått at C++ er et bra valg for studenter (unntatt hvis de skal lære C++).
 

Given these known flaws with C/C++, why is there the popular misconception — among too many programmers and public alike — that C++ is a good language? I genuinely am at a loss to explain it. But here's my suspicion: When C/C++ programmers, used to walking the tightrope without a net, see that a language like Java or Scheme is doing extra work (verifying that any additions really are given numbers instead of strings, making sure arrays indices are legal, etc.), their reaction is “ugh, the computer is doing so much extra work, my programs will run too slow!” Indeed, benchmark programs do run faster in C or C++.

Det handler ikke bare om at det er tregt, men om at det er skittent og "feil".

Å sjekke at man får tall til +-operatoren, er uansett noe C++ gjør, men på kompileringsstadiet. Å gjøre ting run-time som man kan gjøre compile-time, gir ikke bare dårlig ytelse, det er "urent" og uelegant.

Å sjekke om array-indekser er lovlige, er meningsløst, ettersom det spiller liten rolle for sluttbruker om programmet krasjer pga ulovlig indeks, eller om det ... krasjer pga ulovlig indeks, bare med en feilmelding.

Typesikkerhet og lignende må gjøres compile-time, ellers forhindrer det ikke bugs i programvare som er shippet.
 
Tenk nøye igjennom det. Programmet har en spesifikasjon for hva det skal gjøre. Om det gjør noe annet, så er det per definisjon direkte feil.

Om jeg skal regne ut gjennomsnittet av to tall, og skriver (a+b)/2, og programmet begynner å typesjekke, så handler ikke bare om at det går tregere, det er en BUG. For programmet gjør ikke det det skal - å regne - men noe helt annet - å typesjekke.
 

Or even, how important is it to have fast programs?

Om programmet tar tre ganger lenger tid, er det ingen krise. Problemet er at de som tenker sånn som denne fyren, de lager ikke programmer som går tre ganger tregere, ti ganger tregere eller femti ganger tregere. Nei da, det skal gjerne gå både hundre og flere hundre ganger tregere.
 
Ja, det gjør noe. For det tar ikke bare lenger tid, det bruker veldig mye strøm og gir global oppvarming. PCen står ikke å venter, den kjører unødvendige instruksjoner på høygir.
 

But having casual programmers learn C or C++, instead of a high-level language, is not the answer!

Det riktig, det, men det understøtter ikke påstanden om at "C and C++ are Awful Programming Languages".
 

Why use a language which admits the possibility of such “poor quality software”?

Fordi alternative garanterer dårlig kvalitet, vel.

 

Det er mulig Rust er løsningen.

Lenke til kommentar

Inntil noen klarer å lage et språk som har samme eller bedyre ytelse er det rom for C/C++. Til og med hvis det skulle skje ville det være rom for C++/C helt til en stor nok mengde brukere går over til det nye språket.

 

Det er nok mange som missliker språk som C og Fortran fordi de aldri har mestret disse språkene. Hvis man "vokser opp" med Java forstår jeg at man ikke vil ha noe til overs for Fortran. Det man må forsøke å forstå er at det finnes mange bruksområder og at enkelte språk gjør det bedre på noen av de områdene enn andre. Java er nok veldig egnet til enkelte ting, men det er for eksempel helt ubrukelig for ting jeg jobber med. Jeg blir sliten av Java fordi man må skrive så mye, det er så mange ord man må ha med for å gjøre så lite.

 

Alle språk har problemer, men uttalelser som "Språk x er et dårlig" viser kun en mangel på forståelse for IT og forskjellige bruksområder.

EDIT: Det stemmer kanskje at en forskers tid ikke er best brukt på å finne bugs i en Fortran kode, men sånn er det dessverre bare. Det burde også nevenes at mange bugs ikke nødvendigvis ikke kommer fra språket, men måten ligninger og biblioteker er integrert i koden. Det er lett å finne feil som er direkte relatert til språket, men det er utrolig vanskelig å finne en feil i et ligningsystem som består av hundrevis av linjer og ikke linjære ledd. Kanskje tilogmed input fra andre moduler og tabeller. Uansett hvor feilen ligger, man kan ikke simulere komplekse systemer i Java aller Python. Det går for tregt.

Endret av Flin
  • Liker 1
Lenke til kommentar
Gjest Slettet-Pqy3rC

Både C og C++ er helt greie språk; lite "overhead", få "dependencies", god struktur og kjapp eksekvering. Språkene overlater imidlertid mye av ansvaret for oversiktelighet til programmerere, hvilket ikke alltid fungerer. For mange folk gjør en dårlig jobb der.

Endret av Slettet-Pqy3rC
Lenke til kommentar

 

 


 

In C/C++, the programmer (boss) can write "house"[-1] * 37. It's not clear what was intended, but clearly some mistake has been made.

Eeehhh, nei, hvorfor tror han at det er en feil?? Det gir ingen mening å påstå. Det er ikke en feil hvis house er en peker til midt inni en array.
(Det er mulig C++ har definert det til udefinert, men det er ikke en del av negative indeksers natur. Da har han rett i at C++ er et dårlig språk, men han bommer på hvorfor.)


Her leste du nok ikke koden du selv siterte. Det er to problemer her:

- Problem 1: Du klarte ikke å forstå hva koden betyr, selv etter at den (ekstremt) korte kodesnutten ble utpekt som et problem.
- Problem 2: Forfatterens originale klage

Problemet med C++ er kanskje større enn man tror. Endret av oppat
Lenke til kommentar

Ja, jeg så feil. Det er fordi jeg er hjerneskadd og betent i hjernen, og sliter med øynene i tillegg/på grunn av det. Øynene fungerer elendig. Det er ikke en egenskap ved språket, men fordi jeg er på 10%.

 

Jeg testet for øvrig følgende kode med g++, og den oppfører seg på -O0:

int main() {
    char* b = "outside";
    int a = "house"[-2]; // e
    return a;
}
Problemet er selvsagt at standarden ikke definerer dette til å fungere hver gang. Som sagt over, når moderne kompilatorer skal optimalisere, ødelegger de alt. Dette er dumt i et lavnivåspråk. Det er et problem jeg er helt klar over, og det har faktisk vært opphavet til sikkerhetsfeil i linux. Fordi kompilatoren tok ut "overflødige" funksjonskall til en funksjon som overskrev et minneområde med sensitivt materiale med 0, rett før programmet kalte free(). Dermed ble sensitivt materiale liggende i minnet, men dette var umulig å vite ved å inspisere kildekoden.

 

En viss flyfabrikant (jeg tror det var Boeing), bruker visstnok en version av gcc med alle optimaliseringer permanent tatt ut for å forhindre sånt.

  • Liker 1
Lenke til kommentar

For ikke å snakke om de vanvittige reglene for hex (og octal) escape sequences i literal strings... Det skulle vært et fast antall (to) (tre for octal) tegn etter \x. Ikke et uspesifisert antall.

 

#include <string.h>
#include <stdio.h>

int main() {
    char * x = "\xax";
    char * b = "\xab";
    printf("%d", strlen(x));
    printf("%d", strlen(b));
    return 9;
}
Printer:

 

21

 

 

Men det at språket har endel features som er mulig å gjøre feil med, betyr derimot ikke at selve språket er "elendig" totalt sett.

Lenke til kommentar
Gjest Slettet+5132

Her leste du nok ikke koden du selv siterte. Det er to problemer her:

 

- Problem 1: Du klarte ikke å forstå hva koden betyr, selv etter at den (ekstremt) korte kodesnutten ble utpekt som et problem.

- Problem 2: Forfatterens originale klage

 

Problemet med C++ er kanskje større enn man tror.

 

At man overser " . " (anførselstegn) kan skje i alle språk, og er nok mer en menneskelig feil. Hvor mange internett memes er vel ikke på formen "I got a dig bick. You thought it said dick"

 

Og forøvrig, programmet fra Emancipate gir feilmelding i clang:

int main() {
    const char* b = "outside";
    int a = "house"[-2]; // e
    return a;
}
og så kjør clang:

$ clang++ test.cpp
test.cpp:2:17: warning: unused variable 'b' [-Wunused-variable]
    const char* b = "outside";
                ^
test.cpp:3:13: warning: array index -2 is before the beginning of the array
      [-Warray-bounds]
    int a = "house"[-2]; // e
            ^       ~~
2 warnings generated.
i tillegg får du nok en advarsel fra scan-build (clang sin kodeanalysator):

 

$ scan-build clang++ test.cpp
scan-build: Using '/usr/bin/clang-6.0' for static analysis
test.cpp:3:13: warning: array index -2 is before the beginning of the array
      [-Warray-bounds]
    int a = "house"[-2]; // e
            ^       ~~
1 warning generated.
test.cpp:3:5: warning: Assigned value is garbage or undefined
    int a = "house"[-2]; // e
    ^~~~~   ~~~~~~~~~~~
1 warning generated.
scan-build: 1 bug found.
scan-build: Run 'scan-view /tmp/scan-build-2018-06-20-130545-24678-1' to examine bug reports
Det er jo en så god feilmelding som en kan forvente av noe slikt, og det er nok for de fleste prosjekt lurt å veksle mellom clang og gcc for å få mest mulig systemuavhengig kode. Endret av Slettet+5132
Lenke til kommentar
Gjest Slettet+5132

Grunnen til at jeg overså anførselstegnene, ser jeg nå, at var at jeg trodde det første anførselstegnet var starten på hans sitat av koden. Dette er en feil som ikke skjer i en kildekodefil, langt mindre med syntax highlight. :)

Absolutt, dette er en feil som er lett å unngå med verktøy en allerede bør anse som obligatoriske for ethvert softwareprosjekt (syntax-highlighting, statitisk kodeanalyse, og til dels bruk av to uavhengige kompilatorer)

Lenke til kommentar

 

Grunnen til at jeg overså anførselstegnene, ser jeg nå, at var at jeg trodde det første anførselstegnet var starten på hans sitat av koden. Dette er en feil som ikke skjer i en kildekodefil, langt mindre med syntax highlight. :)

Absolutt, dette er en feil som er lett å unngå med verktøy en allerede bør anse som obligatoriske for ethvert softwareprosjekt (syntax-highlighting, statitisk kodeanalyse, og til dels bruk av to uavhengige kompilatorer)

Enig og det var ikke meningen å peke nese. Det er også bra at `-Wall` tar slike eksempler.

 

Men det er likevel langt fra hva C++ gjør og hva som vi egentlig vil.

 

Hvis vi går tilbake til det Emancipate skrev om at et program implementerer en spesifikasjon så kan vi grave litt mer der.

 

F.eks. i språk med kraftfulle typesystemer så prater vi ofte om at typene er proposisjoner og implementasjonen er bevis av proposisjonene.

 

I det rammeverket kan vi si at en kompilator ikke bare skal oversette til maskinkode, men den skal også påpeke overfor programmereren at beviset ikke holder - koden typesjekker ikke - du klarte ikke å bevise proposisjonen.

 

Her henger C++ langt etter selv om man kan gjøre en del av dette med C++ metaprogrammering.

 

Så hva skal en kompilator gjøre når et bevis ikke holder? Man kan enten si at vi bare antar at programmereren implisitt har brukt "absurd"-operatoren i logikk (https://en.wikipedia.org/wiki/Absurdity#Rule_in_logic) overalt hvor kompilatoren finner logiske feil, eller man kan nekte å la programmet kompilere.

 

En tredje mulighet er å sjekke proposisjonen for hver enkelt tilfelle - dvs sjekke ved runtime.

 

Om man nekter å kompilere programmet så kan det bli relativt vanskelig å skrive programmer når typesystemet blir kraftig nok, som f.eks. når man bruker dependent types eller bevisassistenter. Dermed er det å sjekke saker på runtime en helt rimelig vei å gå.

 

Man kan si at C++ tillater ugyldige bevis.  Det andre språk gjør er å tillate at sjekking av bevisførsel skjer på runtime.  Men de sjekker bevisene noe C++ ikke gjør.

 

C++ har imidlertid noen veldig bra saker om man skriver moderne kode, og jeg er helt enig i det Stroustrup sier her - man trenger et system i C++ for å si at "ingen kode som gjør usikre ting kan skrives".

 

Det han egentlig sier, men som han ikke tør å si høyt, er at C++ trenger monade-konseptet.

Endret av oppat
Lenke til kommentar
Gjest Slettet-Pqy3rC

Om man nekter å kompilere programmet så kan det bli relativt vanskelig å skrive programmer når typesystemet blir kraftig nok, som f.eks. når man bruker dependent types eller bevisassistenter. Dermed er det å sjekke saker på runtime en helt rimelig vei å gå.

Altså er runtime type sjekking generelt basert på latskap. Utvikler vil ha enklere rutiner og slappere regler for seg selv og gir f... i all annen effektivitet.

 

Det bør være et mål å skrive koden oversiktlig og korrekt slik at maskinoperasjonene slipper å bruke allverdens tid på å kontrollere programmeringsrbeidet. Spesielt runtime.

 

Man kan si at C++ tillater ugyldige bevis.  Det andre språk gjør er å tillate at sjekking av bevisførsel skjer på runtime.  Men de sjekker bevisene noe C++ ikke gjør.

Hvilket, i min bok, er en god ting. Koden bruker tid & ressurser på selve jobben, ikke på kontroll av om jobben er riktig angitt.
Lenke til kommentar
Gjest Slettet+5132

Er det forøvrig ved typesystemet at skoen trykker for de fleste bruksområder for C++? Metaprogrammering i C++ er for all del ikke pent, og det er litt småting som kunne vært gjort enklere ved metaprogrammering (men nyere versjoner blir alltid bedre), men i all hovedsak er det egentlig ikke der man bruke mesteparten av tida si når man har satt det opp.

 

Bedre RTTI hadde vel i bunn og grunn vært kjekt å ha, men inntrykket mitt er at de som trenger RTTI bruker sitt eget system allerede. 

 

Så da må jeg nesten spørre: Kommer det store eller ofte feil på grunn av typesystemet til C++? Hadde man fått færre problemer, til de bruksområder C++ er tiltenkt, om man innførte monader? Hvilke praktiske anvendelser har dette?

For numeriske program som bruker C++, er vel den store faren ikke i det programtekniske som sådann, men i om den numeriske algoritmen overhodet fungerer eller ei. (du kan bare glemme konvergensbevis for fluiddynamikk før noen vinner 1 million dollar)

Lenke til kommentar

Så da må jeg nesten spørre: Kommer det store eller ofte feil på grunn av typesystemet til C++? Hadde man fått færre problemer, til de bruksområder C++ er tiltenkt, om man innførte monader? Hvilke praktiske anvendelser har dette?

 

Det er behov for å kunne si at "denne modulen bruker ikke pekere", "denne koden er uten sideeffekter", "denne koden aksesserer ikke global tilstand", "denne koden er exception safe", "denne datastrukturen er immutable" etc.

 

Det finnes ikke gode konsepter for dette i C++ som kan komponeres (?? compose).  F.eks. gir ikke const noen fornuftig garanti i C++ siden den ikke smitter interne objekter.  Pekere kan introduseres hvor som helst, global tilstand kan aksesseres hvor som helst, exceptions kan kastes i hytt og gevær.

 

Monader er en måte å uttrykke slike ting, men C++ kommer selvfølgelig til å oppfinne sitt eget vokabular for dette siden det er en sterk NIH-tradisjon i miljøet.

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...