Hallo zusammen
Ich nutze Atmel Studio 6.X und habe vor einiger Zeit in Eclipse gesehen,
dass dort nicht initialisierte Variablen(in z.B. Klassen) als
Compiler-Warning angezeigt werden.
Dies ist im Atmel Studio (trotz "-pedentic") nicht der Fall...wie kann
ich diese Warnings generieren/anzeigen lassen?
Vielen Dank im Voraus
NickNack
casud schrieb:> -Wuninitialized ?
Habe ich eben unter "Toolchain" -> "AVR/GNU C++ Compiler" ->
"Miscellaneous" angehängt, allerdings fehlen die gewünschten warnings
immer noch
Es muss auch ein gewisser Grad an Optimierung aktiviert sein, damit der
Compiler überhaupt eine Datenflussanalyse macht. Hast du es schon mit
-O2 oder -Os probiert?
Wenn das auch nicht hilft: Hast du ein kurzes Stück Testcode, bei dem
das Problem auftritt?
Nick Nack schrieb:> nicht initialisierte Variablen(in z.B. Klassen)
Ich bin mir nicht sicher, ob auch Compound-Variablen (also Strukturen,
Arrays, Objekte und dergleichen) auf Uninitialisiertheit geprüft werden.
Yalu X. schrieb:> Es muss auch ein gewisser Grad an Optimierung aktiviert sein, damit der> Compiler überhaupt eine Datenflussanalyse macht. Hast du es schon mit> -O2 oder -Os probiert?
Weder "O2" noch "OS" bringen die gewünschten Ausgaben.
Dies einer der Aufrufe:
avr-g++.exe" -funsigned-char -funsigned-bitfields -I".." -O2
-ffunction-sections -fdata-sections -fpack-struct -fshort-enums -mrelax
-g3 -Wundef -pedantic -mmcu=atmega1284p -c -Wuninitialized -MD -MP -MF
"testSuite/TestBase.d" -MT"testSuite/TestBase.d"
-MT"testSuite/TestBase.o" -o "testSuite/TestBase.o"
"../testSuite/TestBase.cpp"
Ich erstelle noch ein kurzes Testprogram für hier
Atmel Studio 6.1
Optimierungslevel: None(-O0)
Debug Level: Maximum (-g3)
All warnings, warnings as error, pedantic, pedantic warnings as errors
other flags: -std=c++11
1
#include<stdint.h>
2
3
intmain(void)
4
{
5
uint8_ti;
6
if(i==10)
7
i=0;
8
}
9
10
// 'i' is used uninitialized in this function [-Werror=uninitialized]
Dieser Code schnipsel erzeugt deinen Fehler! Der Fehler kommt natürlich
nur wenn du lesend auf eine nicht initialisierte Variable zugreifst.
grüße
Bei Klassenvariablen/structs erscheint diese warnung nicht (zumindestens
kann ich sie dort nicht forcieren)! Das heist allerdings nicht, das die
variable initialisiert wird! (wie man im simulator/debugger ja
überprüfen kann)
Nick Nack schrieb:> return this->shouldGenerateWarning;
Woher soll der Compiler wissen dass an dieser Stelle
"shouldGenerateWarning" nicht initialisiert ist? GCC ist schon ziemlich
schlau, aber über mehrere Funktionen weg den Ablauf zu analysieren ob
eine Variable zuvor initialisiert wurde, das kann er nicht...
Nick Nack schrieb:> TestClass::TestClass()> {> // here should variable "shouldGenerateWarning" be initialized
Nö, muss gar nicht. In nicht-"constexpr"-Konstruktoren kann man
Member-Variablen von built-in typen sehr wohl uninitialisiert lassen,
was auch sehr oft gemacht wird. Schau aber mal hier:
http://stackoverflow.com/questions/2099692/easy-way-find-uninitialized-member-variables/2911740#2911740Kaj schrieb:> Das heist allerdings nicht, das die> variable initialisiert wird! (wie man im simulator/debugger ja> überprüfen kann)
Wird sie nicht, nicht-statische und nicht-globale Variablen mit built-in
Typen werden nicht automatisch initialisiert, steht dann irgendein
zufälliger Unsinn drin.
Sie ist aber Element einer globalen Variable und wird damit automatisch
mit false initialisiert. Insofern ist das Beispiel etwas schlecht
gewählt.
Man könnte aber die Variable test einfach lokal (und nicht static) in
main definieren. Dann bleibt das Element shouldGenerateWarning
tatsächlich uninitialisiert, und der Compiler warnt aus den bereits
genannten Gründen trotzdem nicht.
Vielleicht ist da das eine oder andere statische Analysetool etwas
gründlicher.
Yalu X. schrieb:> Vielleicht ist da das eine oder andere statische Analysetool etwas> gründlicher.
Man kann immer Fälle konstruieren, in denen ein Analysetool, welches
nicht den kompletten Code in allen Source Code Files analysiert, eine
fehlende Initialisierung nicht detektieren kann.
Genau deshalb bin ich kein Freund von blindem Vertrauen in derartige
Warnungen. Wenn sie kommen, ist es ein nettes Hilfsmittel. Aber in
erster Linie ist der Programmierer selbst dafür verantwortlich, dass
alles korrekt abläuft. Genau deshalb verdienen wir unsere Brötchen, weil
wir auch auf solche Sachen ein Auge werfen und uns darum kümmern und uns
nicht darauf verlassen, dass ein Compiler alles findet.
Yalu X. schrieb:> Man könnte aber die Variable test einfach lokal (und nicht static) in> main definieren. Dann bleibt das Element shouldGenerateWarning> tatsächlich uninitialisiert, und der Compiler warnt aus den bereits> genannten Gründen trotzdem nicht.
Mein GCC warnt aber schon:
tictactoe schrieb:> Mein GCC warnt aber schon:
Dann teil das mal alles in ein paar nette Files auf, so wie man das in
der Praxis haben wird, wenn die Projekt mal ein bißchen größer werden.
hugo.h
tictactoe schrieb:> Mein GCC warnt aber schon:
Mist, ich habe wohl meinen eigenen Beitrag nicht gelesen:
Yalu X. schrieb:> Es muss auch ein gewisser Grad an Optimierung aktiviert sein, damit der> Compiler überhaupt eine Datenflussanalyse macht. Hast du es schon mit> -O2 oder -Os probiert?
Ja, mit -O2 oder -Os warnt auch mein GCC :)
Karl Heinz schrieb:> Dann teil das mal alles in ein paar nette Files auf, so wie man das in> der Praxis haben wird, wenn die Projekt mal ein bißchen größer werden.>> ...>> warnt er jetzt immer noch?
Wie zu erwarten war, weil der Compiler immer nur eine cpp-Datei auf
einmal anschaut: Nein.
Hier hätte aber ein ordentliches Analysetool (frag mich jetzt nicht,
welches) eine gute Chance gehabt, den Fehler zu finden, weil diese Tools
i.Allg. den Datenfluss dateiübergreifend verfolgen.
Aber auch das beste Analysetool stößt irgendwann an seine Grenzen, schon
alleine deswegen, weil die Frage der Verwendung einer uninitialisierten
Variable nicht allgemein entscheidbar ist.
Auch wenn die automatisierte Fehlersuche nicht perfekt ist, bedeutet
jeder vom Programmierer übersehene, aber vom Tool entdeckte Fehler am
Ende einen Fehler weniger.
PS: Will man uninitialisierte Variablen garantiert ausschließen, nimmt
man einfach eine funktionale Programmiersprache anstelle von einer
imperativen :)
Karl Heinz schrieb:> Dann teil das mal alles in ein paar nette Files auf, so wie man das in> der Praxis haben wird, wenn die Projekt mal ein bißchen größer werden.> warnt er jetzt immer noch?
Nö, wie denn auch :-)
Nimm mal Konstruktor und Destruktor raus (die tun ja eh nichts), dann
ist die Warnung wieder da.
Aber das zeigt nur, was du schon geschrieben hast:
Karl Heinz schrieb:> Aber in> erster Linie ist der Programmierer selbst dafür verantwortlich, dass> alles korrekt abläuft. Genau deshalb verdienen wir unsere Brötchen...
Wenn man schon eine Konstruktor schreibt, dann soll der auch tun, was er
verspricht.
tictactoe schrieb:> Karl Heinz schrieb:>> Dann teil das mal alles in ein paar nette Files auf, so wie man das in>> der Praxis haben wird, wenn die Projekt mal ein bißchen größer werden.>>> warnt er jetzt immer noch?>> Nö, wie denn auch :-)
Genau das ist der springende Punkt.
Ich hab nichts gegen die Warnungen. Die sind durchaus sinnvoll.
Was aber nicht sinnvoll ist: sich darauf zu verlassen, dass
uninitialisierte Variablen vom Compiler angemerkt werden würden. Also
den Umkehrschluss zu machen: Ich hab keine Warnung, daher hab ich keine
uninitialisierte Variablen.
> Karl Heinz schrieb:>> Aber in>> erster Linie ist der Programmierer selbst dafür verantwortlich, dass>> alles korrekt abläuft. Genau deshalb verdienen wir unsere Brötchen...>> Wenn man schon eine Konstruktor schreibt, dann soll der auch tun, was er> verspricht.
Na komm. So viel Phantasie wirst du ja wohl noch haben, dass ich in
diese struct noch 5 andere Dinge reinpacken könnte, die dann sehr wohl
eine Behandlung in einem Konstruktor benötigen würden. Das sollte
eigentlich klar sein, dass ich ein Beispiel soweit abspecke, um den
Punkt herauszuarbeiten und zu diskutieren auf den ich raus will, ohne
noch 8 andere Nebenschauplätze zu haben. Der Punkt ist, dass ein
Compiler nicht alle uninitialisierten Variablen feststellen kann. Woraus
folgt, dass ein blindes Verlassen auf die Warnung bzw. deren
Nichterscheinen, tödlich sein kann. Etwas das gerade Neulinge gerne
übersehen.
Karl Heinz schrieb:>> Wenn man schon eine Konstruktor schreibt, dann soll der auch tun, was er>> verspricht.>> Na komm. So viel Phantasie wirst du ja wohl noch haben, dass ich in> diese struct noch 5 andere Dinge reinpacken könnte, die dann sehr wohl> eine Behandlung in einem Konstruktor benötigen würden.
Er meinte das etwas anders: Einer, der seine Brötchen mit Programmieren
verdient, wird einen Konstruktor so schreiben, das der das Objekt auch
wirklich konstruiert, wozu insbesondere die Initialisierung gehört.
Dann stellt sich die Frage nach uninitialisierten Membervariablen gar
nicht erst.