Hi guten Tag,
vlt. hat jemand eine Lösung für meinen fehlerhaften C Code.
Ich verwende eine Bibliothek:
ich übergebe den pointer auf einen pointer auf eine Struktur an eine
Funktion
f(ptr->ptr->Struktur)
dann möchte ich etwas verändern in der Struktur:
ptr->ptr->struktur.chip_count = 123;
dann wieder zurück in der main lese ich den Wert:
print_uart(ptr->ptr->struktur.chip_count)
Und was kommt raus:
12931298739813812738
IRGENDWAS (obwohl vlt. ist dieser Wert wichtig)
Das gleiche mache mich mit einer Kopie dieser Funktion die aber diesmal
in der Main liegt...
Damit funktioniert es. Es kommt wieder 123 raus.
---------------
Hat jemand eine Idee
Liegt es an einer Compiler Optimierung von clang?
marschmello schrieb:> Liegt es an einer Compiler Optimierung von clang?
Höchstwahrscheinlich ein Fehler im Code. Zeige den doch mal. Am besten
ein reduziertes Beispiel, das man direkt kompilieren und ausprobieren
kann, welches den Fehler zeigt.
marschmello schrieb:> ich übergebe den pointer auf einen pointer auf eine Struktur an eine> Funktion
und
> f(ptr->ptr->Struktur)
sind aber zwei Paar Stiefel.
1
structfoo*pBar;
2
f(&pBar);
würde das Beispiel vielleicht passender beschreiben.
marschmello schrieb:> Ich verwende eine Bibliothek:> ich übergebe den pointer auf einen pointer auf eine Struktur an eine> Funktion> f(ptr->ptr->Struktur)
Schau dir den Typ den der Member Structur im struct hat nochmal nach,
btw. den, der f(T) als Argument nimmt. Ist das wirklich ein Pointer?
Oder übergibst du effktiv nur eine Struktur? Das sieht man hier ja
nicht.
marschmello schrieb:> 12931298739813812738
Das ist nicht das was bei dir raus kommt...das ist irgendwas was du da
hingetippert hast.
Fehlerbeschreibungen funktionieren anders.
Der Zusammenhang im Code fehlt.
Danke für die Antwort.
Wollte das erst mal verbal erfragen.
Ich nehme an es ist ein Compiler-Fehler.
Habe wie gesagt zwei gleiche Funktionen mit gleichem Inhalt. Die aus der
Main funktioniert. Die aus der Bibliothek übernimmt nicht alle Werte.
Habe jetzt mal die Funktion mit deren Structurzugriffen
nachprogrammiert.
Hier der Code aus einem online Compiler,sodass er ausführbar ist. Er
besteht aus einer main.c und einer state.h
Ziel ist chip_count durch die Funktion zu verändern.
Das klappt hier auch.
Im Original wird z.B. nur mein "cookie" verändert mein "chip_count" aber
aber erhält einen seltsamen (?) Wert.
Ich schaue mal wie ich bei clang die Compiler-Einstellung verändern
kann...
https://www.onlinegdb.com/_________________________________________
main.c
marschmello schrieb:> Ich nehme an es ist ein Compiler-Fehle
Das ist sehr unwahrscheinlich, Fehler in Compilern, insbesondere in C,
sind sehr selten.
Setze doch mal im GDB einen Watchpoint auf die Variable nachdem du sie
verändert hast und lasse das Programm laufen. Vielleicht wird sie
irgendwo überschrieben (Buffer Overflow o.ä.). Oder einfach Schritt für
Schritt laufen lassen und die Variable im Auge behalten.
marschmello schrieb:> Habe im Anhang nochmal eine kurze Version..> Hätte ich zuerst posten müssen.
Wenn der Fehler dort nicht auftritt, bringt das wenig.
Hi Niklas,
ok habe jetzt noch keinen Watchpoint gesetzt sondern immer so drauf
geschaut.
Werde ich einfach mal machen :)
Also denkst du nicht, dass es an der Compiler Optimierungsstufe liegen
könnte?
marschmello schrieb:> Also denkst du nicht, dass es an der Compiler Optimierungsstufe liegen> könnte?
Theoretisch kann es einen Bug im Optimizer geben, aber das ist sehr
unwahrscheinlich. Viel wahrscheinlicher ist es, dass du einen Fehler im
Code hast, welcher eben nur bei bestimmter Optimierungsstufe ausgelöst
wird. Da hilft es nur den Fehler zu suchen, denn der kann auch später
unter anderen Bedingungen wieder auftreten; einfach nur die Optimierung
abzuschalten ist Symptome bekämpfen.
marschmello schrieb:> Ich nehme an es ist ein Compiler-Fehler.
Wenn ich eines in den letzten 30 Jahren nicht hatte, dann waren das
Compiler-Fehler.
Das Problem saß immer vor dem Bildschirm. Nur Anfänger glauben noch an
Compiler-Fehler.
hmm.. der Code soll nur für ein paar Sekunden laufen. Wenn er tut was er
soll wäre das also erst mal nicht schlimm.
Aber natürlich wäre es schade wenn dann ein Fehler sogar diesen kleinen
Abschnitt beeinträchtigen würde.
Für mich wäre deswegen beides interessant. Sowohl die Optimierung zu
reduzieren als auch den Fehler zu finden .
_________
Natürlich denke ich auch nicht, dass der Compiler einen Fehler hat. Ich
denke eher, dass im besten Fall die Optimierungsstufe das Problem ist.
Cmake unterdrückt mir außerdem sehr viele Fehler.
Dort liegt wahrscheinlich auch ein großes Problem
Also ich schau mir grad deine "kurze Version" an und irgendwie
verstehe ich den Sinn hinter dem Aufbau nicht so ganz.
In main erstellst du eine Struktur und einen Pointer der auf diese
zeigt, ok.
Dann übergibst du diesen Pointer, bis jetzt verständlich.
Nun erzeugst du mit malloc eine neue Struktur im Speicher, weißt dieser
neuen Struktur einen Wert zu und setzt den übergebenen Pointer auf
diese.
Dann ist doch klar das du die urprüngliche Struktur aus der main() nicht
änderst...oder sehe ich das falsch. Mir ergibt sich der Sinn nicht so
wirklich.
marschmello schrieb:> 12931298739813812738> IRGENDWAS (obwohl vlt. ist dieser Wert wichtig)
Das riecht schwer danach, dass du die Adresse mit Print ausgibt. Ins
blaue geraten dereferenzierst du nicht korrekt.
Stell die Warnstufe für Compilerwarnungen auf Maximum und beseitige
nach und nach dei Ursachen für die Warnungen
An
marschmello schrieb:> printf ("\ninst get() adress of inst:%d", inst);
sieht man, dass du die nicht beachtest, denn der Formatspecifier für
Pointer ist %p.
>Dann ist doch klar das du die urprüngliche Struktur aus der main() nicht>änderst...oder sehe ich das falsch. Mir ergibt sich der Sinn nicht so>wirklich.
ah stimmt die erste angelegte Struktur in der Main ergibt keinen Nutzen.
Hatte ich als test drin...
Der Pointer zeigt nach malloc bzw. nach (*inst)= vtss_state; sowieso
woanders hin!
In der Main möchte ich nach vtss_inst_create() dann mit dem pointer auf
die neue Adresse weiterarbeiten.
In vtss_inst_create() habe ich dabei auch chip_count verändert:
>Stell die Warnstufe für Compilerwarnungen auf Maximum und beseitige>nach und nach dei Ursachen für die Warnungen>An>marschmello schrieb:>> printf ("\ninst get() adress of inst:%d", inst);>sieht man, dass du die nicht beachtest, denn der Formatspecifier für>Pointer ist %p.
Ja ich denke auch, dass das die Lösung ist.
Allerdings für mich momentan sehr aufwendig.
marschmello2 schrieb:> In der Main möchte ich nach vtss_inst_create() dann mit dem pointer auf> die neue Adresse weiterarbeiten.
Dann würde ich das anders schreiben.
Ich zeig dir gleich wie ich es meine.
marschmello2 schrieb:> Hatte ich als test drin...
Diese ganzen Tests sind ziemlich verwirrend!
marschnmelllo schrieb:> Allerdings für mich momentan sehr aufwendig.
Dann wird es Zeit damit anzufangen, das wird sonst immer schlimmer.
marschnmelloo schrieb:> hmm.. der Code soll nur für ein paar Sekunden laufen. Wenn er tut was er> soll wäre das also erst mal nicht schlimm.
Das Problem ist, dass solche Fehler eben nicht nur bei eingeschalteter
Optimierung auftreten können, sondern z.B. beim Ändern anderer
Compiler-Optionen, Updaten des Compilers, Ändern von Abhängigkeiten,
Umsortieren des Code... Solche Fehler sind Tretminen, die früher oder
später zum Problem werden. Daher besser früher als später finden.
marschmello2 schrieb:> (genau das funktioniert aber nicht bei meinem Original)
Dann ist wahrscheinlich irgendwo ganz anders ein Problem. Wie gesagt,
Watchpoints können bei sowas enorm hilfreich sein und mit etwas Glück
den Fehler sofort finden. Selbst wenn du dieses Codestück flickst und
zum Laufen bringst, kann das ursprüngliche Problem später wieder
zuschlagen. Reduziere deinen Code auf das Minimum, bei dem das Problem
reproduzierbar auftritt, und zeige das Ergebnis. "Keine Zeit" gilt nicht
- Debugging gehört dazu!
marschnmelloo schrieb:> Dort liegt wahrscheinlich auch ein großes> Problemadd_target_compile_flags(base PRIVATE "" "-Wno-unused-parameter"> "-Wno-pedantic" "-Wno-format" "-Wno-sign-conversion"> "-Wno-switch-default" "-Wno-conversion" "-Wno-unused-variable"> "-Wno-undef" "-Wno-unused-but-set-variable" "-Wno-unused-function"> "-Wno-implicit-function-declaration" "-Wno-uninitialized")
Das ist in der Tat schlecht. Entferne alle "-Wno-" -Optionen und füge
"-Wall -Wextra" hinzu. Vielleicht weist dich das sogar schon auf den
Fehler hin.
Möchtest du sowas machen? Oder habe ich dich da jetzt falsch verstanden?
Finde dieses ganze
- vtss_state_s
- vtss_state_t
- vtss_state_s* vtss_inst_t
zwar sehr verwirrend, aber gut.
Mal unabhängig von der Funktionalität (wurde ja schon geschrieben) sehe
ich da insbesondere die Fehler:
Zeile 20 -> Du machst da einen malloc für die Größe der Pointeradresse,
nicht für die Größe deines struct. Das führt dann auch dazu, dass
vtss_state->chip_count = 12121; irgendwas unvorhergesehenes machen wird,
weil der Speicherbereich so gar nicht da ist.
Am Ende wird der allokierte Speicher nicht freigegeben -> du hast hier
ein memory leak. (das ist jetzt nicht die Ursache für dein Problem,
solltest du aber trotzdem beheben, kann später zu Problemen führen)
Chris schrieb:> Am Ende wird der allokierte Speicher nicht freigegeben
Stimmt, das habe ich jetzt in der main() auch vergessen,
sollte man unbedingt noch einfügen.
Chris schrieb:>Zeile 20 -> Du machst da einen malloc für die Größe der Pointeradresse,>nicht für die Größe deines struct.
Wichtiger Punkt. Diesen Punkt verstehe ich nämlich noch nicht!
> Das führt dann auch dazu, dass> vtss_state->chip_count = 12121; irgendwas unvorhergesehenes machen wird,> weil der Speicherbereich so gar nicht da ist.
(Es "funktioniert" im online-compiler und in einer gleichen Funktion in
meiner Arbeitsumgebung. ( leider nicht bei der Bibliotheksfunktion))
**Liegt hier einfach der Fehler?**
______________________________________
Anmerkung nur damit keine Verwechslung entsteht wegen ähnlicher Namen:
struct vtss_state_s{}
vtss_state_t ;
typedef vtss_state_s *vtss_inst_t;
_______________________
Anhang : screenshots aus dem original code wo der Fehler auftritt
Chris schrieb:> Zeile 20 -> Du machst da einen malloc für die Größe der Pointeradresse
Nein, das ist ein "*" zum dereferenzieren, das ist zwar eher unüblich so
aber sollte stimmen. Hier zu sehen: https://godbolt.org/z/roqcz8xqPmarschmello2 schrieb:> (Es "funktioniert" im online-compiler und in einer gleichen Funktion in> meiner Arbeitsumgebung. ( leider nicht bei der Bibliotheksfunktion))
Valgrind oder Address Sanitizier würden diesen Fehler sofort finden
(also falsche Größe an malloc übergeben).
Niklas G. schrieb:> Valgrind oder Address Sanitizier
Wäre natürlich interessant. Ich sehe in VSC zum Beispiel:
vscode-valgrind
v0.0.1
krosf
6,980
Address Sanitizier sehe ich jetzt noch nicht
Niklas G. schrieb:> Chris schrieb:>> Zeile 20 -> Du machst da einen malloc für die Größe der Pointeradresse>> Nein, das ist ein "*" zum dereferenzieren, das ist zwar eher unüblich so> aber sollte stimmen. Hier zu sehen: https://godbolt.org/z/roqcz8xqP
Oh ja stimmt, allerdings ist es trotzdem falsch, weil der Inhalt von
vtss_state ein Pointer ist (vtss_state wurde in Zeile 17 als Pointer mit
dem struct deklariert, der in sich den Pointer hat) -> Ich habe das in
der Tat falsch gesehen, aber es dürfte trotzdem falsch sein
> marschmello2 schrieb:>> (Es "funktioniert" im online-compiler und in einer gleichen Funktion in>> meiner Arbeitsumgebung. ( leider nicht bei der Bibliotheksfunktion))>> Valgrind oder Address Sanitizier würden diesen Fehler sofort finden> (also falsche Größe an malloc übergeben).
Dass das manchmal funktioniert und manchmal nicht ist üblich, wenn man
auf Speicherbereiche zugreift, die "einem" nicht gehören. Manchmal steht
da noch das drin was man fälschlicherweise reingeschrieben hat, manchmal
wird das aber auch von etwas anderem überschrieben.
>Chris schrieb:>>Zeile 20 -> Du machst da einen malloc für die Größe der Pointeradresse,>>nicht für die Größe deines struct.>Wichtiger Punkt. Diesen Punkt verstehe ich nämlich noch nicht!
Naja, malloc allokiert Speicher mit der angegebenen Größe in Bytes.
sizeof(vtss_state) würde jetzt hier die Größe einer Adresse nehmen, weil
vtss_state ein pointer zu einem pointer ist.
sizeof(*vtss_state) würde jetzt hier die Größe einer Adresse nehmen,
weil *vtss_state die Adresse des darin befindlichen Pointers ist.
Immernoch davon abgesehen, dass der Code nicht so richtig sinnvoll ist,
probiere mal in Zeile 17 das Pointer Sternchen wegzunehmen. Das müsste
die Sache lösen.
Chris schrieb:> Immernoch davon abgesehen, dass der Code nicht so richtig sinnvoll ist,
Hier ist der Originalcode:
https://github.com/microchip-ung/mesa/blob/master/base/ail/vtss_api.c
Werde das jetzt mal ohne Sternchen testen.
(Ich kann das malloc auch einfach aus dem Code streichen. Habe aber
gestern glaube ich das gleiche Verhalten beobachtet! Also der Wert wurde
auch nicht übernommen.
Das kann ich auch noch mal debuggen)
Chris schrieb:> Oh ja stimmt, allerdings ist es trotzdem falsch, weil der Inhalt von> vtss_state ein Pointer ist
Hä? vtss_state_t ist ein struct, es wird genau sizeof(vtss_state_t)
allokiert und auf einen vtss_state_t-Pointer zugewiesen. Das sollte
genau passen.
Chris schrieb:> weil> vtss_state ein pointer zu einem pointer ist.
Nein, es ist ein Pointer auf struct.
Chris schrieb:> Das müsste> die Sache lösen.
Nö, das macht's schlimmer!
marschmello2 schrieb:> Ich kann das malloc auch einfach aus dem Code streichen.
Das einfach so zu löschen macht es ebenfalls schlimmer, weil du dann
irgendwo in den Speicher hinein schreibst.
Mir scheint, du solltest mal ein Buch mit Grundlagen zu C lesen, dann
wird hier einiges klarer. C hat viele Fallstricke, viele Dinge die den
Anschein haben zu funktionieren sind falsch und fallen dir später auf
die Füße, einfach mit Try and Error alles mögliche zu probieren ohne es
zu verstehen ist nicht zielführend.
Niklas G. schrieb:> Das einfach so zu löschen macht es ebenfalls schlimmer
Also soweit ich das Programm verstehe sammelt eine Struktur lauter Werte
um am Ende diese Werte für If-Abfragen zu verwenden.
malloc soll wohl einen Speicherbeich für die Struktur bereitstellen, wo
die Werte nach und nach reingeschrieben werden.
Ich frage mich, ob das nicht auch anders geht. Also durch Nutzen eines
Pointers.
Also das ist das was ich meine mit "malloc löschen".
Am Ende des Programms wo die If-Abfragen sind kann ich aber eigentlich
auch nochmal explizit die Werte in die Struktur schreiben. Das könnte
das Gesamtthema hoffentlich beenden.
marschmello2 schrieb:> Ich frage mich, ob das nicht auch anders geht. Also durch Nutzen eines> Pointers.
Ein Pointer ist aber nur eine Adresse und enthält erstmal keinerlei
Speicher für das Strukt. Den Speicher musst du dir erstmal reservieren,
wie z.B. mit malloc. Das gezeigte malloc ist auch korrekt und das wirst
du wahrscheinlich auch nicht loswerden können. Dir fehlt
Grundlagenwissen, so wird das nichts.
marschmello2 schrieb:> Das könnte> das Gesamtthema hoffentlich beenden.
Nein. Der Fehler ist ganz woanders, ein Buffer Overflow o.ä. Du tüftelst
an Symptomen herum. Der gezeigte Code, und auch der von mesa, ist
korrekt. Werkzeuge wie Watchpoints, Address Sanitizer, Valgrind könnten
hier eventuell blitzschnell Licht ins Dunkel bringen. Bis dahin raten
wir noch etwas und hadern mit malloc herum...
Oliver S. schrieb:> Was ist denn jetzt überhaupt das Problem?>> Suchst du einen Fehler in dem mesa-Code von github, oder in deinem> eigenen Code? Alles sehr wirr...
Also ich habe diesen mesa-Code in meinen Arbeitsbereich in Visual Studio
Code mit CMake eingebunden.
Dadurch musste ich sehr viele Fehler unterdrücken damit das Programm
läuft. Allerdings sind darunter sehr viele unbedeutende Fehler die
einfach sagen: avoid maigc numbers.
Jetzt ist mir aufgefallen, dass die Struktur die nach und nach mit
Werten gefüllt werden soll nur teilweise korrekt gefüllt wird.
Als Vergleich habe ich diese Funktion die aus der vtss_api.c stammt in
der main abgeschrieben create_test(). Damit wurden dann alle gecodeten
Werte übernommen.
Auch im online compiler wurden alle Werte übernommen
Toller Code-Stil, überall sind "*_t" echte Typen außer bei
"vtss_inst_t", da ists ein Pointer. Lesbarer Code ist was anderes. Hätte
man den typedef einfach nur für die Struktur gemacht und überall
explizit mit "*" gearbeitet wüsste jeder was Sache ist. So muss man erst
mal das Gehirn verknoten.
Lasse das Programm im Debugger laufen und setze einen Breakpoint auf
vtss_api.c, Zeile 288, sowie in deine main-Funktion beim Abfragen von
chip_count. Starte das Programm.
Wenn der Breakpoint in vtss_api.c:288 auftritt, setze einen Watchpoint
auf vtss_state->chip_count. Notiere dir die Adresse von vtss_state.
Lasse das Programm weiter laufen. Wenn der Breakpoint in der main zuerst
auftritt, vergleiche die Adresse der vtss_state-Instanz mit der
notierten; es wird vermutlich eine Diskrepanz geben. Dann wurde der
Pointer nicht korrekt zurück gegeben. Wenn stattdessen die Ausführung
irgendwo anders stehen bleibt weil der Watchpoint auslöst, ist genau
DORT der Fehler. Das kann in einem völlig anderen Codeteil sein, den wir
noch gar nicht gesehen haben.
marschmelllo2 schrieb:> Jetzt ist mir aufgefallen, dass die Struktur die nach und nach mit> Werten gefüllt werden soll nur teilweise korrekt gefüllt wird.>> Als Vergleich habe ich diese Funktion die aus der vtss_api.c stammt in> der main abgeschrieben create_test(). Damit wurden dann alle gecodeten> Werte übernommen.> Auch im online compiler wurden alle Werte übernommen
Und was sagt dir das?
Der Fehler steckt nicht dort, wo du ihn vermutest, sondern ganz
woanders. Und nach dem bisherigen Verlauf dieses Threads hier steckt der
mit Sicherheit irgendwo in deinem Code, nicht in dem Mesa-Zeugs von
github.
Wie Andreas auch schon anmerkte, ist der Mesa-Lib-Code grässlich, was
schnell zu Fehlern in der Anwendung führen kann. Trotzdem liegen die
Fehler in der Anwendung, also in deinem Code.
Bau ein minimalistisches Beispiel, mit dem du den Fehler reproduzieren
kannst, und stell das hier ALS ANHANG ein.
Oliver
Ja genau. Ich hoffe ich schaffe das z.B. mit den Watchpoints, die das
Programm unterbrechen, wenn eine Variable geändert wird.
Direkt nach (*inst)= vtss_state erhält eine Variable aber z.B einen
falschen Wert und chip_count wird 0.
Ich schau mir auch noch mal an ob allgemein die Adresszuweisungen Sinn
ergeben.
Vielen Dank bis dahin!
Hab im Anhang nur auch noch mal mein Debuggingversuch
marschmelllo2 schrieb:> Direkt nach (*inst)= vtss_state erhält eine Variable aber z.B einen> falschen Wert und chip_count wird 0.
Sehr verdächtig. Auf was zeigt inst direkt vor dieser Zuweisung? Auf
welche Adresse zeigt vtss_state in dem Moment? Klingt als würdest du
hier auf einen ungültigen Zeiger zugreifen.
Also in deinem Screenshot weist du *inst nie zu, d.h. an den markierten
Stellen dereferenzierst du einen nicht initialisierten Zeiger, schreibst
Daten an irgendeine Adresse, und dann kann halt alles passieren.
Niklas G. schrieb:> Sehr verdächtig. Auf was zeigt inst direkt vor dieser Zuweisung? Auf> welche Adresse zeigt vtss_state in dem Moment? Klingt als würdest du> hier auf einen ungültigen Zeiger zugreifen.
Er greift da auf gar nichts zu. Das macht alles der Code in der lib.
Er stellt nur fest, daß irgendwann irgendwie irgendwo später der Wert
überschrieben wurde.
Oliver
der Inhalt ist vor
(*inst) = vtss_state;
meiner Meinung nach die Adresse der struct aus dem der main die ich zum
test da habe.
Wenn man mit der Maus drüber geht steht dort nämlich diese Adresse.
Wurde auch noch in der Main angezeigt als Adresse der Struktur.
Außerdem habe ich das gerade getestet mit:
sprintf(pr, "\r\n*befcontent of pointer to inst: %p", (void *)(*inst));
Wodurch auch diese Adresse angezeigt wird
vtss_inst zeigt vor
(*inst) = vtss_state;
auf
sprintf(pr, "\r\n*bef content vtss_state:%p", (void *)vtss_state);
ich nehme an die Adresse wird von memset bereitgestellt.
danach zeigt (*inst) auf die gleiche Adresse wie vtss_state
sprintf(pr, "\r\n*content vtss_state:%p\n", (void *)vtss_state);
sprintf(pr, "\r\n* content of pointer to inst: %p\n", (void *)(*inst));
zurück in der main zeigt inst auf:
sprintf(pr, "\r\n*content of inst: %p", (void *)inst);
immer noch wie bei vtss_state und *inst
in der main bleibt die adresse von inst selber gleich
Niklas G. schrieb:> Also in deinem Screenshot weist du *inst nie zu, d.h. an den markierten> Stellen dereferenzierst du einen nicht initialisierten Zeiger, schreibst> Daten an irgendeine Adresse, und dann kann halt alles passieren.
inst ist die adresse vom pointer inst aus der main
um eine variable zu ändern mache ich:
(*inst) was dem pointer entspricht
und (*inst)->variable was einem variablenzugriff entrspicht
... zumindest denke ich das :D
das war bei mir im Code um zu testen.
Im originalcode schreiben die alles in vtss_state und dann geben die dem
pointer (*inst) die adresse von malloc also da wo vtss_state draufzeigt.
Kurze Fassung nochmal:
marschmelllo2 schrieb:> vtss_state->cookie = 123;> vtss_state->create = *create;> (*inst) -> create = *create; // beispielsweise...> (*inst) = vtss_state;
Warum hantierst du überhaupt mit 2 Instanzen rum, einer aus der main und
einer in vtss_inst_create erzeugten?
marschmelllo2 schrieb:> Im originalcode schreiben die alles in vtss_state und dann geben die dem> pointer (*inst) die adresse von malloc also da wo vtss_state draufzeigt.>> Kurze Fassung nochmal:
Wenn die Zeile 6 so im Code stehen würde, dann müsste inst bereits bei
Funktioneintritt auf einen gültigen Pointer zeigen. In dem Falle würde
diese Art von Zuweisung bewirken, das die Struktur auf die der Pointer
auf den inst beim Funktionseintritt zeigt geändert wird, nicht aber die
neu allokierte vtss_state Struktur. Deren Adresse wird nämlich erst in
Zeile 7 in den Pointer auf den inst zeigt geschrieben.
Nochmal zum Thema. Dein Code ist falsch! vtss_state_t ist bereits ein
Pointer. Wenn Du eine Variable "vtss_state_t *vtss_state" definierst,
dann ist vtss_state ein Pointer-Pointer. Mit dem
malloc(sizeof(*vtss_state_t)) allokierst Du also den Speicher für einen
"Pointer" und nicht für die Datenstruktur. Desweitern, sieht man in
deinem Screenshot wunderbar, das Du mitnichten auf dem frisch
allokierten "vtss_state" rumhantierst, sonder auf (*inst) welches noch
überhaupt nicht auf den frisch allokierten Speicher gesetzt wurde. Passt
also nicht zu deinem Codebeispiel von oben. Wenn Du die Zuweisung "*inst
= vtss_state" machen würdest-, wie sie im original Mesa Code steht -
dann würde Dir der Compiler sofort ne Warning oder einen Error geben
weil es unterschiedliche Typen sind. Der einzige Grund, warum Dein
Programm in Zeile 265 nicht direkt abstürzt ist, dass Du zufälligerweise
gerade irgendwo in Deinem Call Stack rumschreibst der später nicht mehr
gebraucht wird.
Schaue Dir nochmal ganz genau den original Mesa code an und versuche zu
verstehen warum dort "vtss_state_t vtss_state;" deklariert wird und
nicht "vtss_state_t *vtss_state;". (Hat was mit meinem Kommentar ganz
oben zu tun) Dann schaue genau, wann dort wo zugewiesen wird.
Niklas G. schrieb:> Das definiert vtss_inst_t als Pointer auf vtss_state_s. Aber es ging um> vtss_state_t, und das ist definiert als Alias von struct vtss_state_s:
Urks. Ich nehm (fast) alles zurück. Das die Schreibzugriffe aber im
Nirvana landen nicht :-)
> Warum hantierst du überhaupt mit 2 Instanzen rum, einer aus der main und> einer in vtss_inst_create erzeugten?
Stimmt habe ich nicht kommentiert.
War nur ein Test ob sich Werte ändern in einer Teststruktur wo (*inst)
hinzeigt. Zurück in der Main wollte ich die Variablenänderung in der
Teststruktur sehen.
Diese Frage hatte auch Andreas M. gerade:
>In dem Falle würde>diese Art von Zuweisung bewirken, das die Struktur auf die der Pointer>auf den inst beim Funktionseintritt zeigt geändert wird, nicht aber die>neu allokierte vtss_state Struktur. Deren Adresse wird nämlich erst in>Zeile 7 in den Pointer auf den inst zeigt geschrieben.
Ja genau das war ein Test ob der Pointer-Pointer-Zugriff auf eine
Teststruktur in der Main funktioniert.
1
(*inst)->create=*create;// Ändere Teststruktur in der Main
2
(*inst)=vtss_state;// Zeige nicht mehr auf die Teststruktur
___________________________________________________________>vtss_state_t ist bereits ein Pointer
Ich denke auch dass es eher eine Alias ist.
1
typedefstructvtss_state_s
2
{
3
...
4
}vtss_state_t;
Ich denke vtss_inst_t ist ein Pointer auf struct_state_s
1
typedefstructstate_s*vtss_inst_t
Die Namen der Pointer/Strukturen sind sehr ähnlich.
__________________________________>Ich nehm (fast) alles zurück. Das die Schreibzugriffe aber im>Nirvana landen nicht :-)
Falls nicht schon getan, beschreib' das bitte mit dem Nirvana.
Niklas G. schrieb:> Das ist in der Tat schlecht. Entferne alle "-Wno-" -Optionen und füge> "-Wall -Wextra" hinzu. Vielleicht weist dich das sogar schon auf den> Fehler hin.
Werde wohl langsam aber sicher die Fehler prüfen müssen.
marschmelllo2 schrieb:> Werde wohl langsam aber sicher die Fehler prüfen müssen.
Na die schnellste Möglichkeit diesen Fehler zu finden wurde dir schon
genannt, dauert mit etwas Glück 1 Minute:
Niklas G. schrieb:> Lasse das Programm im Debugger laufen und setze einen Breakpoint...
Entferne aber vorher allen Testcode und den Tanz mit den 2 Instanzen.
marschmelllo2 schrieb:> Ja genau das war ein Test ob der Pointer-Pointer-Zugriff auf eine> Teststruktur in der Main funktioniert.
Das muss funktionieren
marschmelllo2 schrieb:> Falls nicht schon getan, beschreib' das bitte mit dem Nirvana.
Zeig bitte nochmal deinen vollständigen Code also Aufrufer und die
Funktion, die obigen Beispiele passen irgendwie nicht zu den
Screenshots. Hänge das am besten als Datei an.
Andreas M. schrieb:> marschmelllo2 schrieb:>> Ja genau das war ein Test ob der Pointer-Pointer-Zugriff auf eine>> Teststruktur in der Main funktioniert.>> Das muss funktionieren
Funktioniert nicht korrekt. Es wird wieder nur cookie übernommen und
chip_count wird etwas anderes: "0xcce530d7"
Hab die Funktion vor ein paar Tagen mal selber in die Main geschrieben.
Damit hat es dann einfach funktioniert.
Habe den Teil der Main und die create() nochmal im Anhang.
Brauchst du noch mehr Code dazu?
marschmelllo2 schrieb:> Funktioniert nicht korrekt. Es wird wieder nur cookie übernommen und> chip_count wird etwas anderes: "0xcce530d7"
Ich würde vermuten dass der Wert sehr wohl übernommen wird. Er wird nur
irgendwann später wieder durch etwas anderes überschrieben,
wahrscheinlich durch einen Zugriff auf einen ungültigen Zeiger. Ein
Data-Watchpoint würde diese Stelle identifizieren.
Um das noch mal zu sagen: Der gezeigte Code ist hässlich, aber
korrekt. Da weiter dran rum zu basteln bringt nichts. Du musst
systematisch debuggen.
marschmelllo2 schrieb:>> Das muss funktionieren>> Funktioniert nicht korrekt.
Die Grundfunktionen der Sprache C funktionieren. Du suchst immer noch an
der falschen Stelle.
marschmelllo2 schrieb:> Habe den Teil der Main und die create() nochmal im Anhang.> Brauchst du noch mehr Code dazu?
Lass doch deinen selbsgeschriebenen Versuche weg. Die haben mit deinem
Problem nichts zu tun. Zeig deinen Code mit der Original-lib, der nicht
funktioniert.
Sourcedateien haben eine Endung. Immer. Also lass doch einfach das .c da
dran, dann kann Forensoftware damit umgehen, und dir besser geholfen
werden.
Oliver
marschmelllo2 schrieb:>>> Ja genau das war ein Test ob der Pointer-Pointer-Zugriff auf eine>>> Teststruktur in der Main funktioniert.>>>> Das muss funktionieren
Habe dabei auch (*inst) nicht mit vtss_state überschrieben. Sodass dann
die Adresse gleich war... Aber wie gesagt es wurde nicht überschrieben.
__________________________________>Entferne aber vorher allen Testcode und den Tanz mit den 2 Instanzen.
Meinst du einfach so nah am Original wie möglich?
Testcode versuche ich zu vermeiden/ verringern. Macht das wirklich
unleserlich.
______________________________________________________________> Werde wohl langsam aber sicher die Fehler prüfen müssen.>Na die schnellste Möglichkeit diesen Fehler zu finden wurde dir schon>genannt, dauert mit etwas Glück 1 Minute:
Data Watchpoint setzen und CMake anpassen=> nach und nach Fehler beheben
meinst du damit oder?
Data Watchpoint kenne ich noch nicht so gu t. Habe gestern einen Test
gemacht mit einem "break on value change"... Muss das nochmal genauer
anschauen!
______________________________________________________________
Hier der Link zur vtss_inst_create():
https://github.com/microchip-ung/mesa/blob/master/base/ail/vtss_api.c
Hier wird vtss_inst_create() aufgerufen:
Zeile 731
https://github.com/microchip-ung/mesa/blob/master/phy_demo_appl/appl/vtss_appl_10g_phy_venice.c
marschmelllo2 schrieb:> Meinst du einfach so nah am Original wie möglich?
Nochmal im Klartext: Der Mesa-Code auf github funktioniert. Darin
brauchst du nicht nach Fehlern zu suchen.
Was genau versuchst du eigentlich?
Oliver
Oliver S. schrieb:> Was genau versuchst du eigentlich?
Habe mich nur gewundert warum chip_count nicht den richtigen Wert hat
wenn ich in main die Struktur über meinen Pointer abfrage.
Identische Funktionen die ich zum Testen in der Main angelegt habe
ändern den Wert hingegen korrekt. Auch andere Versuche funktionieren.
Nur wenn ich genau diese Funktion aus der Bibliothek aufrufe geht das
nicht.
Da ich so etwas noch nicht gesehen habe, wusste ich nicht was ich genau
machen soll. Jetzt weiß ich, dass ich mit Watchpoints arbeiten muss oder
meine unterdrückten Fehler behandeln muss.
marschmelllo2 schrieb:> Data Watchpoint setzen und CMake anpassen=> nach und nach Fehler beheben> meinst du damit oder?
An CMake musst du nichts anpassen. Du musst das Programm lediglich im
Debugger starten, die oben aufgelisteten Schritte durchlaufen
(Breakpoints & Watchpoints) und du hast wahrscheinlich den Fehler. Geht,
wie schon 3x gesagt, schneller als das Schreiben eines Beitrags.
marschmelllo2 schrieb:> Data Watchpoint kenne ich noch nicht so gu t.
Dann wird es Zeit das zu lernen. Der Debugger, und Watchpoints, sind
sehr mächtige Werkzeuge mit denen man vertrackte Fehler schnell finden
kann. Viel schneller als nach Gutdünken Zeilen zu löschen...
Niklas G. schrieb:> und du hast wahrscheinlich den Fehler.
also bin da schon ein paar mal mit dem Debugger lang. Und konnte bisher
keine Auffälligkeiten sehen außer, dass nach (*inst) = vtss_state der
Fehler kommt.
An dieser Steller müsste ich mit dem Debugger detaillierter schauen was
los ist...
marschmelllo2 schrieb:> An dieser Steller müsste ich mit dem Debugger detaillierter schauen was> los ist...
Musst du nicht. An der Stelle ist gar nichts los.
Oliver
marschmelllo2 schrieb:> also bin da schon ein paar mal mit dem Debugger lang. Und konnte bisher> keine Auffälligkeiten sehen außer, dass nach (*inst) = vtss_state der> Fehler kommt.
Das ist aber sehr auffällig. Ist das auch noch der Fall nachdem du all
den seltsamen Test-Code und auch diese andere Test-Instanz gelöscht
hast? Du hast jetzt so viele Versionen gezeigt dass ich nicht mehr
mitkomme wo das Problem auftritt.
marschmelllo2 schrieb:> An dieser Steller müsste ich mit dem Debugger detaillierter schauen was> los ist...
Dann mach das doch einfach mal. Pointer-Adressen prüfen, schauen ob
alles da hin zeigt wo es soll. Wenn "(*inst) = vtss_state" tatsächlich
die Variablen-Inhalte beeinflusst zeigt "inst" nicht da hin wo es soll.
Der Stack könnte auch korrumpiert sein. Der Address Sanitizer und der
UB-Sanitizer können helfen.
Wie groß ist das Gesamtprojekt, wie viele Abhängigkeiten hat es, kannst
du es in Gänze hochladen?
Niklas G. schrieb:> Das ist aber sehr auffällig. Ist das auch noch der Fall nachdem du all> den seltsamen Test-Code und auch diese andere Test-Instanz gelöscht> hast?
Ja. Dadurch habe ich ja erst nach und nach Testcode eingefügt um eine
alternative zum Debugger zu haben.
>Dann mach das doch einfach mal. Pointer-Adressen prüfen, schauen ob>alles da hin zeigt wo es soll. Wenn "(*inst) = vtss_state" tatsächlich>die Variablen-Inhalte beeinflusst zeigt "inst" nicht da hin wo es soll.
Ja werde das nochmal machen. Kann sein, dass ich was übersehe.
>Der Stack könnte auch korrumpiert sein. Der Address Sanitizer und der>UB-Sanitizer können helfen.
Es wurden ja mindestens zwei Tools genannt die ich mir anschauen werde.
>Wie groß ist das Gesamtprojekt, wie viele Abhängigkeiten hat es, kannst>du es in Gänze hochladen?
Müsste ich leider erst prüfen.
Hmm, also von dem code würde ich erwarten das er die 123 ausgibt. Vom
Ablauf her:
- Zeile 43 -> chip_count in vtss_state wird auf 123 gesetzt
- Zeile 57: main::inst wird auf vtss_state gesetzt
- Zeile 27: inst sollte auf die selbe struktur zeigen wie zeile 43
benutzt
Fraglich ist was Zeile noch 47-48 machen. Kommt denn malloc ein gültiger
Pointer zurück?
Im Debugger könntest Du dir beim Steppen testweise mal die Adresse in
vtss_state notieren (Zeile 38) und dies dann mit der Adresse in inst,
Zeile 26 vergleichen. Da muss der gleiche Zahlenwert stehen.
Alles sehr verwirrend, mal bezeichnet "inst" einen Pointer (main) und
mal einen Pointer Pointer (vtss_inst_create).
Andreas M. schrieb:> Zeile 43
Sag bitte auf welchen Code du dich beziehst. Habe die Stellen gerade
nicht gefunden. Hätte die Code-Teile besser betiteln sollen :P
Andreas M. schrieb:> Hmm, also von dem code würde ich erwarten das er die 123 ausgibt.
Das wurde jetzt ja schon öfter festgestellt. Die drei Zeilen sind ja nun
kaum mißzuverstehen.
Nur fehlt dem TO da einfach die Einsicht, daß der Fehler damit ganz
woanders zu suchen ist.
Das kann ganz vorne losgehen: Fehler im Linkerscript, in der
Stackinitialisierung, in der Heapinitialisierung, oder halt woanders im
Programm.
Oliver