Explizite Speicherfreigabe
-
Klar geht's anders, ist aber nicht besonders empfehlenswert und verringert nur unnötig die Robustheit des Codes.
-
Ok, aber wie bekomme ich denn den Speicher in der selben Ebene wieder gelöst, bzw. wie kann ich beispielsweise diese Funktion anders/besser realisieren:
char* BSTR2char(const BSTR bstr) { int bstrLength = SysStringLen(bstr); unsigned long multiByteLength = WideCharToMultiByte(CP_ACP, NULL, bstr, bstrLength, NULL, 0, NULL, NULL); char* charBuffer = (char *) malloc(multiByteLength + 1); WideCharToMultiByte(CP_ACP, NULL, bstr, bstrLength, charBuffer, multiByteLength, NULL, NULL); charBuffer[multiByteLength] = 0; return charBuffer; }
Gruß, Thomas
-
groovemaster schrieb:
Klar geht's anders, ist aber nicht besonders empfehlenswert und verringert nur unnötig die Robustheit des Codes.
das kann ich nicht nachvollziehen. wenn funktion1 'weiss' dass funktion2 eine heapadresse zurückgibt, ist doch alles bestens. macht f1 eben 'free' und gut is'. nach deiner ansicht dürfte selbst 'malloc' sich nicht so verhalten, ne?
-
net, komm runter. wir reden hier nicht von "machbar", sondern von "bestes verfahren".
-
Ok, so wie ich das verstehe, muss ich die doSomething-Funktion so aufrufen:
BSTR hellostring = sayHello(); char* phello = BSTR2char(hellostring); doSomething(phello); SysFreeString(hellostring); free(phello);
Wenn das nicht umständlich ist...
Da lob ich mir den Garbage Collector unter Java..
Gruß, Thomas.
-
thomas, es gibt GCs fuer C, aber C [selbst] hat nun mal keinen und das akzeptierst du oder du nimmst ne andere sprache (vielleicht D? das hat nen GC)
-
net schrieb:
das kann ich nicht nachvollziehen. wenn funktion1 'weiss' dass funktion2 eine heapadresse zurückgibt
Weiss sie aber nicht. Punkt.
Das weiss höchstens der Programmierer, wenn er eine entsprechende Doku parat hat.
Ich will mich aber deswegen nicht streiten. Wenn du's so machen willst, dann mach es so. Beschwer dich aber hinterher nicht, wenn du Ressourcenlöcher stopfen musst. Für mich ist es jedenfalls angehemer, wenn ich nach einem Leck suche und mich auf Reservierungs-/Freigabepaare verlassen kann, anstatt an einer Stelle die Reservierung zu haben und dann nach was weiss ich wievielen Freigabestellen suchen zu müssen. Und das auf unterschiedlichen Ebenen.net schrieb:
nach deiner ansicht dürfte selbst 'malloc' sich nicht so verhalten, ne?
Wie verhalten? Hab ich was verpasst?
Thomas++ schrieb:
Ok, aber wie bekomme ich denn den Speicher in der selben Ebene wieder gelöst, bzw. wie kann ich beispielsweise diese Funktion anders/besser realisieren
Indem du es so machst wie die meisten Funktionen der stdlib oder WinAPI, du übergibst einfach das Ziel als weiteren Parameter.
foo(dest, src, maxlen)
Die Speicherfreigabe ist immer noch aussen, die Reservierung aber eben auch. Ausserdem würde ich deine Funktion entkoppeln, die Berechnung der Länge und die eigentliche Umwandlung getrennt behandeln. Dann hast du auch maxlen.
Das mag zwar auf den ersten Blick in der Anwendung mehr Aufwand sein, ist es im Endeffekt auch. Solange du aber keinen GC hast, ist es jedenfalls der sauberere Weg.Eine andere Möglichkeit wäre noch, wenn du das ganze aus einem anderen Sichtwinkel betrachtest. Dazu definierst du den umgewandelten String einfach als eine Art "Objekt". Dementsprechend stellst du zwei Funktionen zur Verfügung:
char* CreateMyStringFromBSTR(const BSTR); DeleteMyString(char*);
CreateMyStringFromBSTR wäre dann deine jetztige BSTR2char Funktion, und in DeleteMyString würdest du dann einfach free aufrufen. Damit wäre das Ressourcenhandling auch wieder auf einer Ebene und vernünftig abstrahiert. Der Client bekommt dann von der dynamischen Speicherreservierung nichts mit, da es für ihn nur dieses "Objekt" gibt, welches er erzeugt und wieder löscht.
-
Kannst du nicht C++ nehmen? Da kann man das super gut kapseln.
-
c.rackwitz schrieb:
net, komm runter. wir reden hier nicht von "machbar", sondern von "bestes verfahren".
ist mir bewusst. trotzdem halte ich dass verfahren von thomas für geeigneter. euer vorschlag mit 'foo(dest, src, maxlen)' um das speicherhandling gewaltsam auf einer ebene zu halten, ist für den aufrufer ganz schön ätzend. gibt er zu wenig speicher an, dann gibt die funktion einen fehlercode zurück und man muss es nochmal versuchen, free, nochmal malloc (oder realloc) usw. thomas' funktion macht alles selbständig - das ist viel praktischer so. den einzigen vorteil der 'foo(dest, src, maxlen)'-methode sehe ich darin, dass der aufrufer bestimmen kann, wo der speicher liegt, den die funktion benutzen soll. also @thomas: lass dich nicht verunsichern...
btw: grooves methode mit 'CreateStringFromBSTR' und 'DeleteStringFromBSTR' ist dagegen ok. könnte man z.b. ganz einfach so machen:
#define DeleteStringFromBSTR(s) free(s)
-
.......... schrieb:
Kannst du nicht C++ nehmen? Da kann man das super gut kapseln.
Du meinst, ich sollte z.B. statt BSTR CComBSTR verwenden?
-
net schrieb:
gibt er zu wenig speicher an, dann gibt die funktion einen fehlercode zurück und man muss es nochmal versuchen, free, nochmal malloc (oder realloc) usw.
Naja, ich habe ihm doch geschrieben, wie er an maxlen kommt. Da gibt es keinen Grund, zu wenig Speicher zu übergeben.
-
groovemaster schrieb:
Naja, ich habe ihm doch geschrieben, wie er an maxlen kommt. Da gibt es keinen Grund, zu wenig Speicher zu übergeben.
klar, du empfiehlst ihm eine wunderbar nützliche funktion in zwei funktionen aufzudröseln. vielleicht schlägst du nächstes mal vor, die funktion ganz wegzulassen und den code an die stellen zu kopieren, wo er ihn braucht? dann haste ja auch das speicherhandling auf einer ebene...
-
"wunderbar nützliche funktion"? Naja, das ist wohl eher subjektiv. Niemand hat begauptet, dass C nur aus Syntaxzucker besteht. Vieles ist oftmals im Vergleich zu anderen Sprachen aufwändiger. Das ist aber auch ein Grund, wieso C so universell einsetzbar ist. Wieso also von den Prinzipien abweichen, die man schon seit vielen Jahren aus der stdlib und diversen APIs kennt? Du solltest in Zukunft besser lernen, vernünftig zu argumentieren, anstatt ständig mit irgendwelchen Flames zu kommen. Du hast dem OP einen Vorschlag gemacht, ich habe dem OP einen Vorschlag gemacht, und dabei wollen wir's belassen. Entscheiden muss er letztendlich sowieso selber.
-
groovemaster schrieb:
Du solltest in Zukunft besser lernen, vernünftig zu argumentieren, anstatt ständig mit irgendwelchen Flames zu kommen.
naja, mir fehlt wohl das nötige taktgefühl beim postings schreiben....