Speicherzugriffsfehler
-
würnung schrieb:
Ich bin sogar ziemlich sicher, dass der Compiler bei
City *findCityById (int id) { set<City>::iterator it; for (it = cities.begin(); it != cities.end(); ++it) { City c = *it; City& cn = c; if (c.getId() == id) cn = *it; return &cn; } return 0; }eine Warnung ausgibt, wenn er richtig eingestellt ist (z.B. -Wall -Wextra bei gcc).
Tipp: Du gibst einen Pointer auf eine lokale Variable zurück.
Nein, der Compiler gibt keine Warnung aus

Hier mein Makefile:CXXFLAGS=-Wall CC=$(CXX) PROGRAMS=programm OBJECTS=city.o street.o ALLOBJECTS=$(OBJECTS) $(patsubst %,%.o,$(PROGRAMS)) default: $(PROGRAMS) %.d: %.cc $(SHELL) -ec '$(CC) -MM $(CXXFLAGS) $< | \ perl -pe '"'"'s|($*\.o)[ :]*|\1 $@: |g'"'"' > $@' programm: $(OBJECTS) clean: -rm -f $(ALLOBJECTS) $(ALLOBJECTS:%.o=%.d) $(PROGRAMS) include $(ALLOBJECTS:%.o=%.d)
-
tntnet schrieb:
Beim schnellen überfliegen fällt mir auf, dass Du auf argc < 4 abfragst. Bei argc==4 darfst Du aber nicht auf argv[4] zugreifen sondern nur bis argv[3].
Er darf, aber bei argv[4] sitzt ein Null-Zeiger.
-
tntnet schrieb:
elflaco schrieb:
#include "city.h" #include "street.h" #include <iostream> #include <stdlib.h> int main(int argc, char *argv[]) { if (argc < 4) { cerr << "usage: programm stadt.dat gebiet.dat strasse.dat stadtname" << endl; exit(1); } CityList cl (argv[1]); StreetList sl(argv[3], cl); sl.findReachableCities(cl, sl, argv[4]); cl.printList(); }Ich hoffe, ihr könnt mir helfen!
elflaco
Beim schnellen überfliegen fällt mir auf, dass Du auf argc < 4 abfragst. Bei argc==4 darfst Du aber nicht auf argv[4] zugreifen sondern nur bis argv[3].
Und lass das "using namespace std" weg. Zumindest im Header. Du musst dann nur die Symbole wie cout voll qualifizieren (std::cout ...).
Oh, kleiner Fehler, soll natürlich argc < 5 heißen!
Hmm, ist das schlimm, wenn ich das solasse?
-
elflaco schrieb:
Nein, der Compiler gibt keine Warnung aus

Hier mein Makefile:Stimmt. Nur clang gibt eine Warnung aus.
xx.cc:19:15: warning: address of stack memory associated with local variable 'c' returned [-Wreturn-stack-address] return &cn; ^~ xx.cc:16:13: note: binding reference variable 'cn' here City& cn = c; ^ ~ 1 warning generated.Solltest du auf jeden Fall fixen!
-
würnung schrieb:
elflaco schrieb:
Nein, der Compiler gibt keine Warnung aus

Hier mein Makefile:Stimmt. Nur clang gibt eine Warnung aus.
xx.cc:19:15: warning: address of stack memory associated with local variable 'c' returned [-Wreturn-stack-address] return &cn; ^~ xx.cc:16:13: note: binding reference variable 'cn' here City& cn = c; ^ ~ 1 warning generated.Solltest du auf jeden Fall fixen!
Ok, danke schonmal!
Aber wie am besten? Hab schon was ausprobiert, aber das hat alles nicht zum Erfolg geführt...
-
City *findCityById (int id) { set<City>::iterator it; for (it = cities.begin(); it != cities.end(); ++it) { City& cn = *it; if (cn.getId() == id) return &cn; } return 0; }So zum Beispiel. Wenn nicht wieder so ein Besserwisser kommt. Das ist nicht so sauber aber für einen Anfänger hinreichend korrekt.
Mit Deinem Code erzeugst Du eine Kopie von *it mit
City c = *it; City& cn = c; if (c.getId() == id) cn = *it; return &cn;cist hier eine Kopie von *it und damit eine lokale Variable und cn eine Referenz darauf. Ein Zeiger auf cn zeigt also auf die Lokale Kopiec
-
tntnet schrieb:
City *findCityById (int id) { set<City>::iterator it; for (it = cities.begin(); it != cities.end(); ++it) { City& cn = *it; if (cn.getId() == id) return &cn; } return 0; }So zum Beispiel. Wenn nicht wieder so ein Besserwisser kommt. Das ist nicht so sauber aber für einen Anfänger hinreichend korrekt.
Mit Deinem Code erzeugst Du eine Kopie von *it mit
City c = *it; City& cn = c; if (c.getId() == id) cn = *it; return &cn;cist hier eine Kopie von *it und damit eine lokale Variable und cn eine Referenz darauf. Ein Zeiger auf cn zeigt also auf die Lokale KopiecSo ähnlich hatte ich es auch schon, dann kommt aber:
city.h:72:21: error: invalid initialization of reference of type ‘City&’ from expression of type ‘const City’
-
Ein set mag es nicht so gerne, wenn man seine Elemente einfach so ändert

-
Jockelx schrieb:
Ein set mag es nicht so gerne, wenn man seine Elemente einfach so ändert

Das habe ich auch schon bemerkt...aber wie machs ich dann sonst am besten?

-
Ich weiss nicht, was dein Programm machen soll.
Brauchst du wirklich ein set? Brauchst du wirklich eine Referenz auf das Orginal oder kannst du es auch genauso gut kopieren?
Falls beides mit 'ja' beantwortet wird, überleg dir eine Alternative.
Ein Element 'ändern' in einem set kannst du z.B. mit löschen und einfügen.
-
Jockelx schrieb:
Ein set mag es nicht so gerne, wenn man seine Elemente einfach so ändert

Ach ja richtig. Ich habe gar nicht daran gedacht, dass man die Elemente im set const sind.
Das Problem, wenn das set erlauben würde, die Elemente zu ändern ist, dass die Reihenfolge kaputt gehen könnte und eine binäre Suche dann nicht mehr funktioniert.
Also musst Du entweder auf ein std::vector oder ähnliches ausweichen oder doch gleich richtig und const-correctness lernen. Ändere mal den Rückgabewert von Deiner "findCityBy..."-Methoden in "const City*". Die get-Methoden in City machst Du auch const, so dass Du auf diese über einen const* zugreifen kannst. Es gibt sicher noch ein paar andere stellen, wo Du const ergänzen musst. Das wird Dir dein Compiler sogar sagen. Die Parameter von "findReachableCities" fallen mir gerade noch ins Auge.
-
Wenn ich das richtig intepretiere: Du hast Städte (Knoten) und Straßen (Kanten), die diese Knoten verbinden. Ausgehend von einem Startknoten willst Du alle erreichbaren Knoten finden?
Ist das für die Uni oder privat?
Scheint mir auf jeden Fall eine dankbare Aufgabe für's Forum zu sein, da man viel daran zeigen kann...
SW-Design, Standardbibliothek, Graphentheorie....natürlich nur wenn der OP noch am Ball ist und nicht am Freitag Abgabe war und die Sache damit abgehakt.
