Kleines Speicherproblem bzw malloc Verständnis
-
SKB schrieb:
Hallöchen.
Ich hätte eine kleine Frage zu folgemdem Code-Schnipsel:
[cpp]
bool checkOP (MString *Sender) {
char *query;
MYSQL_RES res;
MYSQL_ROW row;
query=(char)malloc(255);
sprintf(query, "select * from operatorenliste where operator='%s';",Sender->print());
res=SQLGetCommand(query);
if ((mysql_fetch_row(res)>0)||(*Sender=="abcde"))
return(1); // Hier wird die Funktion verlassen und der Speicher nicht freigegeben
MString x;
x="/w ";
x=x+Sender->print();
x=x+" Du bist nicht berechtigt diesen Befehl ausführen zu lassen.";
ChatBot.say(x.print());
free (query);
return(0);
}
[/cpp]Irgendwie wird bei dem Schnipsel der Speicher nicht wieder freigegeben.
Müsste ich quasi hingehen und in der main function einmal den Speicher für malloc bestimmen und dann in jedem void() wieder re-alloc(ieren) :)?
Oder ist das ganz normal, dass der Speicher mit 16kb belegt wird und dann nicht gelöscht wird?
Für eine kleine Hilfe bedanke ich mich im voraus.
Gruß,
SKB
-
SKB schrieb:
Also könnte ich alle meine void's, die solch einen malloc und free benutzen genau so schreiben, wie ich es eben getan habe, ja?
Solange du alles was du mit malloc allokierst auch mit free freigibst, kannst du dies machen (Auch wenn es eher C als C++ Code ist, und ich eher die C++ Konstrukte new/delete vorziehe, es sei den es stellt sich an der Stelle als Flaschenhals heraus).
SKB schrieb:
Windows gaukelt mir dann also nur einen vor, dass der Speicher nicht freigeben wurde?
Windows gaukelt dir garnichts vor, es hat tatsächlich für den Prozess den Speicher reserviert. Wann die entgültige Freigabe des Adressraumes durchgeführt wird, ist aber Aufgabe des Betriebssystems, der Taskmanager bekommt es nicht unbedingt mit ob der Speicher als solches "freigegeben" ist. Wenn der Speicher ständig weiterwächst würde ich aber irgendwann dennoch Gedanken machen...
Zudem hast du doch ein Speicherleak...
if ((mysql_fetch_row(res)>0)||(*Sender=="abcde")) return(1);Wenn du hier rein läufst wird das free nicht mehr durchgeführt!
SKB schrieb:
Wieso kann ich mein Projekt eigentlich nicht "einfach so" von Dev C++ von Bloodshed in MS Visual Studio packen? Visual Studio meckert z.B. ständig bei "sprintf" ich solle es in sprintf_s ändern
bzw kann es mit der mysql.h auch nix anfangen 
1. VC++ 2005 verhält sich von den Standardbibliotheken vorsichiger als der Standard (An sich ist die "sichere" Variante okay, aber am Ziel vorbeigeschossen). Es hat Funktionen bereitgestellt die "sicherer" sind als die normalen, sofern du weitgehend portabel schreiben willst (was ich z.B. vorziehe) ist dies aber etwas das ich ignorieren würde. Man kann Warnungen auch deaktivieren, was man (wie in dem Fall) aber nur bewusst tun sollte (Linke immer auf höchster Warnstufe, und schalte nur dann Warnungen aus wenn du dir über die Konsequenzen bewusst bist, und bereit bist diese zu tragen).
Lass raten: Warnung 4996 (Ich stelle sie grad für eine externe Bibliothek aus).
2. mysql.h ist kein Standardheader, demzufolge muss dieser VC++ auch bekannt gemacht werden (sprich: Inkludeverzeichnis bekannt geben).
cu André
-
Danke danke danke

Also, ich glaube, ich bleibe dann erstmal bei dem Bloodshed. Da die Anwendungen nur für mich sind kann ich damit besser ausprobieren

Habe den Code nun einmal umgebaut bzw erweitert. So könnte ich ihn dann lassen?
bool checkOP (MString *Sender) { char *query = new char[100]; MYSQL_RES *res; MYSQL_ROW row; sprintf(query, "select * from operatorenliste where operator='%s';",Sender->print()); res=SQLGetCommand(query); if ((mysql_fetch_row(res)>0)||(*Sender=="abcde")) delete [] query; return(1); MString x; x="/w "; x=x+Sender->print(); x=x+" Du bist nicht berechtigt diesen Befehl ausführen zu lassen."; ChatBot.say(x.print()); delete [] query; return(0); }Gruß,
SKB
-
warum willst du dein query überhaupt auf dem heap mit malloc/new erstellen? in deinem falle reicht doch eine einfache stack-variable:
char query[100];
die wird automatisch ferigegen, da brauchst du dich gar ncit drum kümmern.
-
Ah, ok.
Also dann so?
bool checkOP (MString *Sender) { char query [100]; MYSQL_RES *res; MYSQL_ROW row; sprintf(query, "select * from operatorenliste where operator='%s';",Sender->print());dann noch das delete [] raus und gut ist, ja?
-
... if ((mysql_fetch_row(res)>0)||(*Sender=="abcde")) delete [] query; return(1); ...Jetzt wird das delete[] beim if-Fall ausgeführt nicht aber das return. Zum einen, wie angemerkt kasst du hier auch mit einem normalen Array arbeiten, zum anderen solltest du Klammern...
Nachtrag: Bzw. das return wird nun immer ausgeführt, dein Compiler sollte wenn er gut ist meckern das es "unreachable code" gibt...... if ((mysql_fetch_row(res)>0)||(*Sender=="abcde")) { delete [] query; return(1); } ...Einrücken würde ich dir auch empfehlen...
cu André
-
Ich habe es nun so geschrieben:
bool checkOP (MString *Sender) { char query [100]; MYSQL_RES *res; MYSQL_ROW row; sprintf(query, "select * from operatorenliste where operator='%s';",Sender->print()); res=SQLGetCommand(query); if ((mysql_fetch_row(res)>0)||(*Sender=="abcde")) { return(1); } else { MString x; x = "/w "; x = x + Sender->print(); x = x + " Du bist nicht berechtigt diesen Befehl ausführen zu lassen."; ChatBot.say(x.print()); return(0); } }Was ist eigentlich, wenn ich in dem void noch ein anderes query ausführen möchte? Kann ich dann einfach das char query[100]; neu füllen? Oder erstelle ich dann einfach ein neues?
Gruß,
SKB
-
Also das mit dem Einrücken solltest du noch lernen, üblich sind zum Beispiel die drei folgenden Stile:
int main() { ... if(irgendwas) { ... } else { ... } ... } int main() { ... if(irgendwas) { ... } else { ... } ... } int main() { ... if(irgendwas) { ... } else { ... } ... }Unabhängig was du machst, Einrücken erleichtert das Lesen, du solltest aber versuchen im Stil konsistent zu bleiben. Man findet schneller heraus wozu ein bestimmtes Statement gehört. Ich selber präferiere eigentlich den ersten Stil, das ist aber persönlicher Geschmack (so übersehe ich seltener die öffnende Klammer). Bei sehr kurzen Funktionen (Ein- oder Zweizeiler) nutze ich auch mal den letzteren.
SKB schrieb:
...Was ist eigentlich, wenn ich in dem void noch ein anderes query ausführen möchte? Kann ich dann einfach das char query[100]; neu füllen? Oder erstelle ich dann einfach ein neues?...
Mit dem void???
Aber grundsätzlich: Ja du kannst eine Variable mehrfach verwenden, solltest dies aber nur tun wenn man im Code erkennen kann was gemeint ist (nicht das man später etwas ergänzt und nicht bemerkt das die Variable schon mit anderen Werten als erwartet gesetzt wird). Es gibt einfach nur eine potentielle Fehlerquelle auf die man aufpassen sollte.
cu André
-
Also das Einrücken finde ich bei meinem Beitrag, den ich zuletzt erstellt habe schonmal gar nicht schlecht

Also kann ich hingehen:
char query [100]; sprintf(query, "insert into table (id, name) VALUES ('%s', %s);", z.print(), SenderX->print()); SQLCommand(query); // und hier dann ein neues sprintf sprintf(query, "select * from table where Wert='Wert';"); SQLCommand(query);Zumindest meckert der Compiler da nicht und die Daten werden einwandfrei ausgelesen.
Gruß,
SKB
-
Ja, das geht auf jeden Fall
Und der Variablen-Name passt auch zur Verwendung, deshalb ist das auch noch gut zu lesen.
-
Dankeschön

Also verstehe ich auch richtig, dass das neue sprintf einfach das alte "überschreibt"?
Somit hätte ich ja dann mein malloc() Problem gelöst und alles ist fein

-
SKB schrieb:
Also verstehe ich auch richtig, dass das neue sprintf einfach das alte "überschreibt"?
Ja, das sprintf überschreibt den bestehenden Inhalt mit etwas neuem (was bei längeren Funktionen auch gerne mal übersehen wird ;P aber zu lange Funktionen sollte man eh vermeiden).
cu André
-
Super

Ich danke dir für die schnelle Hilfe. Habe viel gelernt und viel verändert. Seitdem läuft das Prog nun zur vollsten Zufriedenheit
