Komische XC8-Warnung

Gast #5410388
Lesenswert?

Hallo,

ich bekomme komische Warnungen von meinem XC8-Compiler:
1
ATCA_STATUS at_cmd_info(uint8_t *info_dest)
2
{
3
    [...]
4
    for([...])
5
    {
6
        info_dest[i] = i2c_receive();
7
    }
8
    [...]
9
}
1
warning: (1498) pointer (at_cmd_info@info_dest) in expression may have no targets

In dem XC8-Manual steht gar nichts zu einem Fehler/Warnung mit der Nr. 
1498.
Ich denke der Compiler warnt mich davor, dass der Speicher hinter 
`info_dest` zu klein ist. Aber warum? Jemand ne Idee?

Desweiteren gibt es auch Warnungen von Library-Code:
1
/opt/microchip/xc8/v1.45/sources/common/doprnt.c:538: warning: (373) implicit signed to unsigned conversion
2
/opt/microchip/xc8/v1.45/sources/common/doprnt.c:541: warning: (373) implicit signed to unsigned conversion
3
/opt/microchip/xc8/v1.45/sources/common/doprnt.c:757: warning: (373) implicit signed to unsigned conversion
4
/opt/microchip/xc8/v1.45/sources/common/doprnt.c:1316: warning: (373) implicit signed to unsigned conversion
5
/opt/microchip/xc8/v1.45/sources/common/doprnt.c:1317: warning: (373) implicit signed to unsigned conversion
6
/opt/microchip/xc8/v1.45/sources/common/doprnt.c:1500: warning: (373) implicit signed to unsigned conversion
7
/opt/microchip/xc8/v1.45/sources/common/doprnt.c:1524: warning: (373) implicit signed to unsigned conversion
Gast #5410754
Lesenswert?

Danke für die Antwort!

Und wie sage ich dem Compiler, dass der Übergebene Speicher groß genug 
ist?

Wäre das folgende erlaubt?
1
ATCA_STATUS at_cmd_info(uint8_t info_dest[7])

Nicht um ein Array zu erzeugen, sondern um den Compiler mitzuteilen, 
dass der übergebene Puffer mindestens 7 byte umfassen muss.
Moderator #5410869
Lesenswert?

Welchen Typ hat der Rückgabewert von i2c_receive?

Vermutlich ist er vorzeichenbehaftet. Da info_dest[i] vom Typ uint8_t
ist, können damit keine negativen Zahlen dargestellt werden, was zur
Warnung führt.

Wenn du sicher bist, dass durch die implizite Typkonvertierung keine
fehlerhaften Ergebnisse entstehen können, kannst du die Konvertierung
explizit machen und dadurch die Warnung beseitigen:

1
        info_dest[i] = (uint8_t)i2c_receive();

Das alles gilt natürlich nur unter der Voraussetzung, dass i2c_receive()
tatsächlich vorzeichenbehaftet ist. Ist das nicht der Fall, liegt das
Problem woanders. Mit der Größe des Arrays hat das aber nichts zu tun.
Gast #5412088
Lesenswert?

Sorry für die späte Antwort.

Yalu X. schrieb:
> Welchen Typ hat der Rückgabewert von i2c_receive?
i2c_receive hat 'uint8_t' als Rückgabewert.


Ich habe noch folgendes gefunden:
1
And it is basically stating that the pointer passed as argument "uint8_t *buffer" is being dereferenced and since there is no assignment of this pointer on the function it may has no valid address to be dereferenced for. So the compiler believes that before this function is called the pointer was assigned a valid address. Again, I am not worried about this warning.

Ergibt für mich keinen Sinn, da der Compiler den Argumenten beim 
Funktionsaufruf Werte zuweist.

Siehe: http://www.microchip.com/forums/FindPost/958305

Ich habe noch folgendes probiert:
1
ATCA_STATUS at_cmd_info(uint8_t *info_dest)
2
{
3
    if(info_dest == NULL)
4
        return AT_NULLPOINTER;
5

6
    [...]
7
    for([...])
8
    {
9
        info_dest[i] = i2c_receive();
10
    }
11
    i2c_stop();
12
    [...]
13
}

Ändert aber nichts an der Warnung.
#5412104
Lesenswert?

Probier mal.
1
ATCA_STATUS at_cmd_info(uint8_t info_dest[])
2
{
3
    if(info_dest == NULL)
4
        return AT_NULLPOINTER;
5

6
    [...]
7
    for([...])
8
    {
9
        info_dest[i] = i2c_receive();
10
    }
11
    i2c_stop();
12
    [...]
13
}

So ist wenigstens klar, das mit dem Pointer ein Array gemeint ist....
Gast #5412391
Lesenswert?

XC8 schrieb:
> ...
1
ATCA_STATUS at_cmd_info(uint8_t *info_dest)
2
{
3
    [...]
4
    for([...])
5
    {
6
        info_dest[i] = i2c_receive();
7
    }
8
    [...]
9
}
> ...

Kannst du ein minimales, vollständiges Beispiel geben, dass den Fehler 
reproduziert? Also ohne unbekannte Macros (ATCA_STATUS), ohne unbekannte 
Funktionen (i2c_receive), ohne die [...] und mit Compiler-Optionen.

Es werden sich hier vermutlich nicht viele Leute finden, die den XC8 
installiert haben und dir trotz der wenigen Infos helfen wollen.
Gast #5412405
Lesenswert?

Toxic schrieb:
> Ich wuerde einfach mal googeln:
> http://www.microchip.com/forums/m1038697.aspx
>
> und mich bei XC8/PICs-Fragen direkt mit Microchip Forumusern
> unterhalten.

Ge-googled habe ich, aber nach der konkreten Warnung und nicht 
allgemein. Danke für den Link!

mh schrieb:
> Kannst du ein minimales, vollständiges Beispiel geben, dass den Fehler
> reproduziert?

Gerne.
1
uint8_t minimal_beispiel(uint8_t *buffer)
2
{
3
    *buffer = 0xFF;
4
    return 0;
5
}

führt zu
1
attec508a.c:162: warning: (1498) pointer (minimal_beispiel@buffer) in expression may have no targets
2
attec508a.c:162: warning: (759) expression generates no code

Ich denke den 'Generates no code' wird man los, wenn der Wert 0xFF nicht 
ge-hardcoded wird. Spielt aber für das Beispiel keine Rolle.
Gast #5412431
Lesenswert?

Da fehlt mindestens nen include, oder du hast Fehlermeldungen/Warnungen 
unterschlagen.

Aber vermutlich hast du ne ganze Menge andere Sachen unterschlagen:
XC8 schrieb:
> attec508a.c:162
bei 5 Zeilen die du zeigst.

Gibt es die Warnung auch, wenn in der Datei nichts anderes steht außer 
den 5 Zeilen + fehlendes inclcude?
Gast #5412457
Lesenswert?

mh schrieb:
> Da fehlt mindestens nen include, oder du hast Fehlermeldungen/Warnungen
> unterschlagen.

Jaaa. uint8_t ist halt kein Standarddatentyp, dazu muss stdint.h oder 
inttypes.h inkludiert werden (ich vergesse immer welche der beiden es 
ist).

Alternativ nimm halt einfach nur int. Geht genauso.
1
int minimal_beispiel(int *buffer)
2
{
3
    *buffer = 0xFF;
4
    return 0;
5
}
1
attec508a.c:155: warning: (1498) pointer (minimal_beispiel@buffer) in expression may have no targets
2
attec508a.c:155: warning: (759) expression generates no code

mh schrieb:
> Aber vermutlich hast du ne ganze Menge andere Sachen unterschlagen:
> XC8 schrieb:
>> attec508a.c:162
> bei 5 Zeilen die du zeigst.
Naja, ist halt ein Minimalbeispiel. Abgesehen davon ist doch erkennbar, 
dass ich die ganze Funktion gepostet habe. Die anderen Funktionen in der 
Datei sind für das Verhalten vollkommen irrelevant.


mh schrieb:
> Gibt es die Warnung auch, wenn in der Datei nichts anderes steht außer
> den 5 Zeilen + fehlendes inclcude?

Ja.
1
test.c:4: warning: (1498) pointer (minimal_beispiel@buffer) in expression may have no targets
2
test.c:4: warning: (759) expression generates no code
#5412483
Lesenswert?

int minimal() {}

ist von extern sichtbar (da nicht static) und kann deshalb von anderen 
Compilation-Units aufgerufen werden. Wie die das machen,weiß der 
Compiler aber nicht, im Gegensatz zu Aufrufenaus der gerade übersetzten 
Compilation Unit. Also sagt er zur Sicherheit "kann schief gehen".

Man kann sich natürlich darüber streiten, ob diese "keine Katze in der 
Nicrowelle trocken"-Meldung wirklich hilft, aber zumindest kann man MC 
deshalb nicht verklagen.
Leider haben "viele Warnungen" Konjunktur gegenüber "wenige Wichtige" 
und es ist hat "echt hilfreich", wenn die eine Nadel-Warnung in dem 
Haufen Warnung-Heu so stark heraus sticht.
Eventuell kann man dieses Feature des XC8 aber auch ausschalten.
Gast #5412511
Lesenswert?

XC8 schrieb:
> ... Die anderen Funktionen in der
> Datei sind für das Verhalten vollkommen irrelevant.
Du verstehst etwas nicht und Fragst in einem Forum nach Hilfe. Glaubst 
du, dass du die richtige Person bist, um zu entscheiden wo oder was das 
Problem ist?

Du solltest dir mal https://stackoverflow.com/help/mcve durchlesen und 
für deine nächste Problembeschreibung zu Herzen nehmen.

XC8 schrieb:
> mh schrieb:
>> Gibt es die Warnung auch, wenn in der Datei nichts anderes steht außer
>> den 5 Zeilen + fehlendes inclcude?
>
> Ja.

Dann fehlen jetzt noch die Compiler-Optionen
Gast #5412543
Lesenswert?

Teo D. schrieb:
> XC8 schrieb:
>> *buffer = 0xFF;
>
> Hat so kein Ziel -> NULL.
>
> Ruf diese Funktion mal korrekt auf oder initialisiere mal den Pointer
> auf eine gültige Adresse.
> Dann ist bei mir die Warnung auch weg.

Das kann wohl kaum die Lösung sein oder wie soll man das bei 
Bibliotheksfunktionen machen?
#5412561
Lesenswert?

mh schrieb:
> Teo D. schrieb:
>> XC8 schrieb:
>>> *buffer = 0xFF;
>>
>> Hat so kein Ziel -> NULL.
>>
>> Ruf diese Funktion mal korrekt auf oder initialisiere mal den Pointer
>> auf eine gültige Adresse.
>> Dann ist bei mir die Warnung auch weg.
>
> Das kann wohl kaum die Lösung sein oder wie soll man das bei
> Bibliotheksfunktionen machen?

Wenn der Compiler gut ist, sollte er spätestens wenn eine Prüfung auf 
ungleich NULL drin ist, mit der Warnung aufhören. Denn darum geht's ja 
eigentlich:
"Achtung, du dereferenzierst einen Pointer, von dem ich nicht weiß, ob 
er gültig ist"
Gast #5412571
Lesenswert?

Carl D. schrieb:
> Wenn der Compiler gut ist, sollte er spätestens wenn eine Prüfung auf
> ungleich NULL drin ist, mit der Warnung aufhören. Denn darum geht's ja
> eigentlich:
> "Achtung, du dereferenzierst einen Pointer, von dem ich nicht weiß, ob
> er gültig ist"

Wenn das tatsächlich der Grund ist und sich nicht ausschlaten lässt, 
gehört der Compiler in den Müll.

Ich alleine entscheide wo und wann ich einen Pointer auf NULL prüfe. Und 
ich ziehe vor dort zu prüfen, wo der Pointer NULL werden kann und nicht 
da, wo ich ihn benutze.
Gast #5412579
Lesenswert?

Teo D. schrieb:
> 'extern' dazu klöppeln?
Was soll extern bringen?

Teo D. schrieb:
> Ist ja NUR ne Warnung, kein Error.
Jede unsinnige Warnung, die nicht beseitigt werden kann lenkt von echten 
Warnungen ab, und ist damit nicht zu akzeptieren. Was ist, wenn ich 30 
Funktionen habe, die nen Pointer als Argument haben. Wie soll ich dann 
die eine echte Warnung sehen?
#5412597
Lesenswert?

mh schrieb:
> Carl D. schrieb:
>> Wenn der Compiler gut ist, sollte er spätestens wenn eine Prüfung auf
>> ungleich NULL drin ist, mit der Warnung aufhören. Denn darum geht's ja
>> eigentlich:
>> "Achtung, du dereferenzierst einen Pointer, von dem ich nicht weiß, ob
>> er gültig ist"
>
> Wenn das tatsächlich der Grund ist und sich nicht ausschlaten lässt,
> gehört der Compiler in den Müll.
;-)

Wenn stimmt, was weiter oben wohl getestet wurde, daß der XC8 die 
Prüfung nicht erkennt, dann könnte das auch ein "haben wir auch" auf die 
diversen Prüfungen, die clang und GCC drauf haben, sein.

> Ich alleine entscheide wo und wann ich einen Pointer auf NULL prüfe. Und
> ich ziehe vor dort zu prüfen, wo der Pointer NULL werden kann und nicht
> da, wo ich ihn benutze.
In einer Library wäre das aber nicht der beste Ansatz.

Vielleicht bist du aber nur zu jung und kannst Dinge, die Compiler für 
dich erledigen (mangels Bedarf) noch nicht so richtig würdigen. Ich 
schreibe zunehmend größere Programme, als ich sie noch komplett 
überblicken könnte. Da ist man über Hilfe froh ;-)
Gast #5412660
Lesenswert?

Carl D. schrieb:
> In einer Library wäre das aber nicht der beste Ansatz.
Ich sage nicht, dass es für jeden und alles der beste Ansatz ist. Für 
meine Zwecke halte ich es für den besten Ansatz. Andere gewichten die 
Argumente dafür und dagegen anders und kommen zu einem anderen Ergebnis.

Ich habe mal eine Funktion aus einer sehr bekannten Library 
ausgewählt: memcpy. Ich zitiere aus der Beschreibung aus 
http://en.cppreference.com/w/c/string/byte/memcpy, da ich zu Faul bin 
sie aus dem Standard herauszusuchen:
1
The behavior is undefined if either dest or src is a null pointer.

Und tatsächlich weder glibc noch newlib prüfen in memcpy, ob einer der 
Pointer NULL ist.

Es gibt also noch andere Personen, die der Meinung sind, dass es ein 
geeigneter Ansatz ist.
#5412670
Lesenswert?

mh schrieb:
> Carl D. schrieb:
>> In einer Library wäre das aber nicht der beste Ansatz.
> Ich sage nicht, dass es für jeden und alles der beste Ansatz ist. Für
> meine Zwecke halte ich es für den besten Ansatz. Andere gewichten die
> Argumente dafür und dagegen anders und kommen zu einem anderen Ergebnis.
>
> Ich habe mal eine Funktion aus einer sehr bekannten Library
> ausgewählt: memcpy. Ich zitiere aus der Beschreibung aus
> http://en.cppreference.com/w/c/string/byte/memcpy, da ich zu Faul bin
> sie aus dem Standard herauszusuchen:
>
1
> The behavior is undefined if either dest or src is a null pointer.
2
>
>
> Und tatsächlich weder glibc noch newlib prüfen in memcpy, ob einer der
> Pointer NULL ist.
>
> Es gibt also noch andere Personen, die der Meinung sind, dass es ein
> geeigneter Ansatz ist.

Vermutlich ist obiger Text schon ein paar Jährchen alt.
Und es ist ja nicht so, daß man Warnungen nicht ignorieren könnte, wenn 
man weiß, was man tut, nur manchmal bemerkt man solche Sachen einfach 
nicht und es ist immer besser das zur Compile-Zeit zu erfahren.
Und wie hatte mal einer in einem Vortrag (über C++) zu Compiletime 
Exceptions in constexpr gesagt: die werden nicht ausgeliefert.
Gast #5412691
Lesenswert?

Carl D. schrieb:
> Und es ist ja nicht so, daß man Warnungen nicht ignorieren könnte, wenn
> man weiß, was man tut, nur manchmal bemerkt man solche Sachen einfach
> nicht und es ist immer besser das zur Compile-Zeit zu erfahren.

Nur was macht man, wenn man dutzende dieser Warnungen hat, und die 
echten Warnungen nicht mehr sofort sieht?
Ich hab nicht ohne Grund mehrfach nach den Compiler-Optionen gefragt.
#5412709
Lesenswert?

mh schrieb:
> Carl D. schrieb:
>> Und es ist ja nicht so, daß man Warnungen nicht ignorieren könnte, wenn
>> man weiß, was man tut, nur manchmal bemerkt man solche Sachen einfach
>> nicht und es ist immer besser das zur Compile-Zeit zu erfahren.
>
> Nur was macht man, wenn man dutzende dieser Warnungen hat, und die
> echten Warnungen nicht mehr sofort sieht?
> Ich hab nicht ohne Grund mehrfach nach den Compiler-Optionen gefragt.

Ich hab ja nicht gesagt, daß mir dieser Compiler gut gefällt. Er warnt 
vor etwas, dessen Beseitigung er nicht erkennt. Man kann die Warnungen 
anscheinend nicht ausschalten, ...
Manchmal entscheidet man sich eben auch für (oder gegen) eine 
Architektur, weil sie von brauchbaren (nicht) Compilern unterstützt 
wird.
Und so wurde ich dann mit PIC nie warm. Ein Privileg, das ich mir bei 
den kleinen Bastelrechnern daheim leisten kann, auf den dicken Hobeln 
auf der Arbeit nicht.
Gast #5413051
Lesenswert?

Teo D. schrieb:
> Teo D. schrieb:
>> Ruf diese Funktion mal korrekt auf oder initialisiere mal den Pointer
>> auf eine gültige Adresse.
>  Dann ist bei mir die Warnung auch weg

Wir reden aneinander vorbei.
Zeig mal bitte deinen Code.

Carl D. schrieb:
> ist von extern sichtbar (da nicht static) und kann deshalb von anderen
> Compilation-Units aufgerufen werden. Wie die das machen,weiß der
> Compiler aber nicht, im Gegensatz zu Aufrufenaus der gerade übersetzten
> Compilation Unit. Also sagt er zur Sicherheit "kann schief gehen".

Wie kann man eine Funktion denn falsch aufrufen? Wenn ich ein Argument 
weglasse, schlägt die Kompilierung fehl. Zudem weiß der Compiler durch 
die Prototypen (aus den Headern) wie die Funktion aufgerufen werden soll 
(und das in jeder Compilation Unit).
#5413056
Lesenswert?

XC8 schrieb:
> Alternativ nimm halt einfach nur int. Geht genauso.
> int minimal_beispiel(int *buffer)
> {
>     *buffer = 0xFF;
>     return 0;
> }

minimal_beispiel(0x100);

oder

> int minimal_beispiel(int *buffer)
> {
      buffer = 0x100;
>     *buffer = 0xFF;
>     return 0;
> }

Get doch NUR um:

Teo D. schrieb:
> XC8 schrieb:
>> test.c:4: warning: (1498) pointer (minimal_beispiel@buffer) in
>> expression may have no targets
?
Gast #5413074
Lesenswert?

Danke!
Teo D. schrieb:
>> Alternativ nimm halt einfach nur int. Geht genauso.
>> int minimal_beispiel(int *buffer)
>> {
>>     *buffer = 0xFF;
>>     return 0;
>> }
>> minimal_beispiel(0x100);

Ok, so klappt es bei mir auch.
Die Funktionen wurde bei mir noch gar nicht aufgerufen, dass hat der 
Compiler wohl als Anlass genommen sich zu beschweren?!?
(Über die 'Function never called'-Warnung hinaus natürlich).
Gast #5413178
Lesenswert?

Teo D. schrieb:
> XC8 schrieb:
>> Alternativ nimm halt einfach nur int. Geht genauso.
>> int minimal_beispiel(int *buffer)
>> {
>>     *buffer = 0xFF;
>>     return 0;
>> }
>
> minimal_beispiel(0x100);

Teo D. schrieb:
>> int minimal_beispiel(int *buffer)
>> {
>       buffer = 0x100;
>>     *buffer = 0xFF;
>>     return 0;
>> }

Autsch! Ich hoffe der Compiler gibt bei den Beispielen echte Warnungen. 
Sowas wie "assignment makes pointer from integer without a cast". Mal 
davon abgesehen, dass das vermutlich undefined behaviour ist.
#5414567
Lesenswert?

XC8 schrieb:
> Carl D. schrieb:
>> ist von extern sichtbar (da nicht static) und kann deshalb von anderen
>> Compilation-Units aufgerufen werden. Wie die das machen,weiß der
>> Compiler aber nicht, im Gegensatz zu Aufrufenaus der gerade übersetzten
>> Compilation Unit. Also sagt er zur Sicherheit "kann schief gehen".
>
> Wie kann man eine Funktion denn falsch aufrufen? Wenn ich ein Argument
> weglasse, schlägt die Kompilierung fehl. Zudem weiß der Compiler durch
> die Prototypen (aus den Headern) wie die Funktion aufgerufen werden soll
> (und das in jeder Compilation Unit).

z.B.
1
minimal_beispiel(NULL);
Passiert das in einer anderen Compilation-Unit, dann weiß der Compiler 
davon nichts und genau das sagt er.
Wie schon einmal geschrieben scheint er aber nicht schlau genug zu sein, 
eine Prüfung auf !=NULL zu verstehen, deswegen ist das für mich nicht 
einer der Besten seiner Art.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren