Clang vs GCC voor mijn Linux-ontwikkelingsproject

Ik studeer en voor een project gebruiken we C. We hebben GCC en Clang verkend en Clang blijkt veel gebruiksvriendelijker te zijn dan GCC. Daarom vraag ik me af wat de voor- of nadelen zijn van het gebruik van clang, in tegenstelling tot GCC, voor het ontwikkelen in C en C++ op Linux?

In mijn geval zou dit worden gebruikt voor programma’s op leerlingniveau, niet voor productie.

Als ik Clang gebruik, moet ik dan debuggen met GDB en GNU Make gebruiken, of een andere debugger en make-hulpprogramma gebruiken?


Antwoord 1, autoriteit 100%

BEWERKEN:

De gcc-jongens hebben de diagnose-ervaring in gcc (ah-competitie) echt verbeterd. Ze hebben een wikipagina gemaakt om het hierte tonen. gcc 4.8 heeft nu ook een behoorlijk goede diagnose (gcc 4.9x kleurondersteuning toegevoegd). Clang staat nog steeds aan de leiding, maar het gat wordt kleiner.


Origineel:

Voor studenten zou ik Clang onvoorwaardelijk aanbevelen.

De prestaties in termen van gegenereerde code tussen gcc en Clang zijn nu onduidelijk (hoewel ik denk dat gcc 4.7 nog steeds de leiding heeft, ik heb nog geen sluitende benchmarks gezien), maar voor studenten om te leren maakt het toch niet echt uit .

Aan de andere kant is de extreem duidelijke diagnose van Clang zeker gemakkelijker voor beginners om te interpreteren.

Beschouw dit eenvoudige fragment:

#include <string>
#include <iostream>
struct Student {
std::string surname;
std::string givenname;
}
std::ostream& operator<<(std::ostream& out, Student const& s) {
  return out << "{" << s.surname << ", " << s.givenname << "}";
}
int main() {
  Student me = { "Doe", "John" };
  std::cout << me << "\n";
}

Je zult meteen merken dat de puntkomma ontbreekt na de definitie van de Studentklas, toch 🙂 ?

Nou, gcc merkt het ookop een bepaalde manier:

prog.cpp:9: error: expected initializer before ‘&’ token
prog.cpp: In function ‘int main()’:
prog.cpp:15: error: no match for ‘operator<<’ in ‘std::cout << me’
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:112: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>& (*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:121: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ios<_CharT, _Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:131: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:169: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:173: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:177: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/ostream.tcc:97: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:184: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/ostream.tcc:111: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:195: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:204: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:208: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:213: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:217: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:225: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:229: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/ostream.tcc:125: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_streambuf<_CharT, _Traits>*) [with _CharT = char, _Traits = std::char_traits<char>]

En Clang speelt hier ook niet echt de hoofdrol, maar toch:

/tmp/webcompile/_25327_1.cc:9:6: error: redefinition of 'ostream' as different kind of symbol
std::ostream& operator<<(std::ostream& out, Student const& s) {
     ^
In file included from /tmp/webcompile/_25327_1.cc:1:
In file included from /usr/include/c++/4.3/string:49:
In file included from /usr/include/c++/4.3/bits/localefwd.h:47:
/usr/include/c++/4.3/iosfwd:134:33: note: previous definition is here
  typedef basic_ostream<char>           ostream;        ///< @isiosfwd
                                        ^
/tmp/webcompile/_25327_1.cc:9:13: error: expected ';' after top level declarator
std::ostream& operator<<(std::ostream& out, Student const& s) {
            ^
            ;
2 errors generated.

Ik kies doelbewust een voorbeeld dat een onduidelijke foutmelding veroorzaakt (afkomstig van een dubbelzinnigheid in de grammatica) in plaats van de typische “Oh my god Clang read my mind”-voorbeelden. Toch merken we dat Clang de stortvloed aan fouten vermijdt. Het is niet nodig om studenten af te schrikken.


Antwoord 2, autoriteit 29%

Vanaf nu biedt GCC veel betere en completere ondersteuning voor C++11-functies dan Clang. Ook presteert de codegenerator voor GCC betere optimalisatie dan die in Clang (in mijn ervaring heb ik geen uitputtende tests gezien).

Aan de andere kant compileert Clang code vaak sneller dan GCC en geeft het betere foutmeldingen als er iets mis is met je code.

De keuze welke je moet gebruiken, hangt echt af van welke dingen belangrijk voor je zijn. Ik hecht meer waarde aan C++11-ondersteuning en de kwaliteit van codegeneratie dan aan het gemak van compilatie. Daarom gebruik ik GCC. Voor jou kunnen de afwegingen anders zijn.


Antwoord 3, autoriteit 19%

Ik gebruik beide omdat ze soms verschillende, nuttige foutmeldingen geven.

Het Python-project kon een aantal kleine buglets vinden en repareren toen een van de kernontwikkelaars voor het eerst probeerde te compileren met clang.


Antwoord 4, autoriteit 9%

Ik gebruik zowel Clang als GCC, ik vind dat Clang enkele nuttige waarschuwingen heeft, maar voor mijn eigen raytracing-benchmarks – het is constant 5-15% langzamer dan GCC (neem dat natuurlijk met een korreltje zout, maar geprobeerd vergelijkbare optimalisatievlaggen voor beide te gebruiken).

Dus voor nu gebruik ik de statische analyse van Clang en zijn waarschuwingen met complexe macro’s: (hoewel de waarschuwingen van GCC nu ongeveer net zo goed zijn – gcc4.8 – 4.9).

Enkele overwegingen:

  • Clang heeft geen OpenMP-ondersteuning, het is alleen van belang als je daarvan profiteert, maar aangezien ik dat wel doe, is het voor mij een beperking. (*****)
  • Cross-compilatie wordt mogelijk niet zo goed ondersteund (FreeBSD 10 gebruikt bijvoorbeeld nog steeds GCC4.x voor ARM), gcc-mingw is bijvoorbeeld beschikbaar op Linux… (YMMV).
  • Sommige IDE’s ondersteunen het ontleden van Clangs-uitvoer nog niet (QtCreator bijvoorbeeld*****). BEWERK: QtCreator ondersteunt nu de uitvoer van Clang
  • Sommige aspecten van GCC zijn beter gedocumenteerd en aangezien GCC al langer bestaat en veel wordt gebruikt, is het wellicht gemakkelijker om hulp te krijgen met waarschuwingen/foutmeldingen.

***** – deze gebieden zijn in actieve ontwikkeling en kunnen binnenkort worden ondersteund


Antwoord 5, autoriteit 5%

Voor programma’s op studentniveau heeft Clang het voordeel dat het standaard strenger is tov. de C-standaard. De volgende K&R-versie van Hello World wordt bijvoorbeeld zonder waarschuwing geaccepteerd door GCC, maar afgewezen door Clang met enkele behoorlijk beschrijvende foutmeldingen:

main()
{
    puts("Hello, world!");
}

Bij GCC moet je het -Werrorgeven om het echt duidelijk te maken dat dit geen geldig C89-programma is. Je moet ook nog steeds c99of gcc -std=c99gebruiken om de C99-taal te krijgen.


Antwoord 6, autoriteit 2%

Ik denk dat gekletter een alternatief kan zijn.

GCC en clang hebben enkele verschillen in uitdrukkingen zoals a+++++a, en ik heb veel verschillende antwoorden met mijn collega die clang op Mac gebruikt terwijl ik gcc gebruik.

p>

GCC is de standaard geworden en clang zou een alternatief kunnen zijn. Omdat GCC erg stabiel is en het geluid nog in ontwikkeling is.

Other episodes