Hi,
noch mal eine dumme Frage.
Wenn ich einer Funktion einen Pointer übergebe, sollte diese doch den
Inhalt des Pointers ändern können. Warum funktioniert dann diese
Funktion nicht:
#include
From: Volker Kroll
Hi,
noch mal eine dumme Frage. Wenn ich einer Funktion einen Pointer übergebe, sollte diese doch den Inhalt des Pointers ändern können. Warum funktioniert dann diese Funktion nicht: #include
void tester(char*); int main (int argc, char* argv[]) { char *field = "teststring"; tester(field); printf("String: %s\n", field); /* prints teststring not langer String */ return 0; }
void tester(char* test) { test = "langer String"; }
IMHO funktioniert die Zuweisung so nicht ... probier mal: void tester(char* test) { strcpy (test, "langer String"); } Gruß Daniel
On Thu, 2002-07-18 at 14:41, Daniel Bauer / MList wrote:
IMHO funktioniert die Zuweisung so nicht ... probier mal:
void tester(char* test) { strcpy (test, "langer String"); }
Ne, das Ergebnis ist dasselbe (bzw. es gibt einen Segmaentation fault, den ich mit malloc umgangen habe.) Ich fürchte, daß ist wieder ganz trivial und ich mache mich hier zum Nabbel .... V. -- Volker Kroll 4mino AG Chief System Developer Chausseestr. 52 b volker.kroll@4mino.de D-10115 Berlin Tel.: +49-30-2888490-0 Fax.: +49-30-2888490-99
Volker Kroll wrote:
On Thu, 2002-07-18 at 14:41, Daniel Bauer / MList wrote:
IMHO funktioniert die Zuweisung so nicht ... probier mal:
void tester(char* test) { strcpy (test, "langer String"); }
Das ist für sich genommen schon mal richtig, solange durch "äußere Gegebenheiten" sichergestellt ist, daß der Pointer test auf einen Speicherbereich zeigt, der groß genug ist, den neuen String samt abschließendem Null-Byte (in diesem Fall also 14 Bytes) aufzunehmen. Da man aber leicht vergißt, sowas sicherzustellen, stellt so eine Funktion eine gute Fehlerquelle da -- so entstehen die berühmten Buffer-Overflows, auf deren Kappe auch viele Sicherheitslücken gehen.
Ne, das Ergebnis ist dasselbe (bzw. es gibt einen Segmaentation fault, den ich mit malloc umgangen habe.)
In Deinem Testprogramm wird in main() ein konstanter String an tester() übergeben. Nun ist es so, daß String-Konstanten (mit gcc unter Linux) in einem Speichersegment abgelegt werden, daß als read-only markiert ist. Der damit unzulässige Versuch, den String zu überschreiben, also schreibend auf dieses Segment zuzugreifen, wird vom System abgefangen und dem Prozeß als "Segmentation fault" signalisiert (SIGSEGV). Eine mögliche Lösung hat Bernhard ja gezeigt. (Die Variante, bei der in main() mit malloc() ein veränderbarer Speicherbereich für den String reserviert wird.)
Ich fürchte, daß ist wieder ganz trivial und ich mache mich hier zum Nabbel ....
Jain. Wenn man die Pointerei etc. erst einmal richtig verstanden hat, ist das ganze *prinzipiell* recht trivial und logisch, aber trotzdem kann man sich leicht in seinen Pointern verheddern -- gerade, wenn's mal etwas komplexer wird. Eilert -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Eilert Brinkmann -- Universitaet Bremen -- FB 3, Informatik eilert@informatik.uni-bremen.de - eilert@tzi.org http://www.informatik.uni-bremen.de/~eilert/
On Thu, 18 Jul 2002 at 14:41 (+0200), Daniel Bauer / MList wrote:
From: Volker Kroll
noch mal eine dumme Frage. Wenn ich einer Funktion einen Pointer übergebe, sollte diese doch den Inhalt des Pointers ändern können. Warum funktioniert dann diese Funktion nicht: #include
void tester(char*); int main (int argc, char* argv[]) { char *field = "teststring"; tester(field); printf("String: %s\n", field); /* prints teststring not langer String */ return 0; }
void tester(char* test) { test = "langer String"; }
IMHO funktioniert die Zuweisung so nicht ... probier mal:
void tester(char* test) { strcpy (test, "langer String"); }
So einfach nicht: 1. Du darfst einer Konstante keinen anderen Wert zuweisen. 2. Du darfst schon gar nicht einen längeren Wert zuweisen. Du hast doch nur 11 Bytes Speicher (10 Zeichen + \0). strcpy(test, "kurz"); dürfte zwar funktionieren, kollidiert aber mit 1. Kann aber sein, dass der GCC es mit 1. nicht sehr genau nicht. Mit dem bcc32 (Borland/Win) hatte ich diesbezüglich schonmal Probleme. *g* Gruß, Bernhard -- _________ http://www.bwalle.de _________________________________________________ Geld ist besser als Armut - wenn auch nur aus finanziellen Gründen. -- Woody Allen
On Thu, 18 Jul 2002 at 14:24 (+0200), Volker Kroll wrote:
Wenn ich einer Funktion einen Pointer übergebe, sollte diese doch den Inhalt des Pointers ändern können.
Nein. Du kannst nicht den Inhalt des Pointers verändern (d. h. die
Adresse, auf die verwiesen wird) sondern nur den Inhalt des Textes,
indem der Speicher verändert wird, auf den der Pointer zeigt.
Siehe:
,----[ test.c ]-
| #include
Volker Kroll wrote:
Wenn ich einer Funktion einen Pointer übergebe, sollte diese doch den Inhalt des Pointers ändern können.
Du hast keinen Speicherplatz fuer den Text "langer String" reserviert. Der Text "teststring" wird als read-only im text-Segment deines Programmes abgelegt, und dein Schreibzugriff fuehrt dann zum "Segmentation Fault". Bei C und Stringbehandlung ist sehr viel Umsicht angebracht, so dass man jedem nur raten kann das in einer Bibliothek behandeln zu lassen. Ich glaube das die glib ganz gut dafuer geeignet ist, habe aber selbst nicht viel sinnvoll programmiert. http://developer.gnome.org/doc/API/glib/index.html Peter
Volker Kroll
Wenn ich einer Funktion einen Pointer übergebe, sollte diese doch den Inhalt des Pointers ändern können.
Den Inhalt ja, nicht aber den Zeiger selbst.
#include
Warum funktioniert dann diese Funktion nicht: #include
void tester(char*); int main (int argc, char* argv[]) { char *field = "teststring"; tester(field); printf("String: %s\n", field); /* prints teststring not langer String */ return 0; }
void tester(char* test) { test = "langer String"; }
tester bekommt einen Zeiger übergeben, also eine Adresse übergeben.
Die kannst du ändern solang du willst, änderst damit aber nicht den
Zeiger in main. So müsste es ungefähr aussehen, damit es funktioniert:
#include
Hallo Philipp, hallo Bernhard, On Thu, 2002-07-18 at 16:29, Philipp Thomas wrote:
tester bekommt einen Zeiger übergeben, also eine Adresse übergeben. Die kannst du ändern solang du willst, änderst damit aber nicht den Zeiger in main. Aber Vorsicht, das geht nur mit Stringkonstanten gut! Wären die Strings dynamisch alloziert hättest du da ein prima Speicherleck.
wenn Ihr so weiter macht, dann verstehe ich das am Ende wirklich. Vielen Dank, Ihr habt mir wirklich weitergeholfen. Ich hoffe, ich nerve mit derartig trivialen Fragen nicht! Viele Grüße Volker PS: Bernhard: Sagtest Du nicht, daß Du auch Anfänger in C bist? Habe ich vielleicht ein gutes Buch übersehen? Ich habe bisher Kernighan - Ritchie und Stevens: Advanced programming in an unix environment gelesen. So langsam beginne ich auch die Zusammenhänge zu verstehen, aber gerade Pointer und Pointerarithmetik sind mir noch sehr fremd, da es das in den anderen Sprachen, die ich bisher benutzt habe, nicht gab. -- Volker Kroll 4mino AG Chief System Developer Chausseestr. 52 b volker.kroll@4mino.de D-10115 Berlin Tel.: +49-30-2888490-0 Fax.: +49-30-2888490-99
Hallo, On Thu, 18 Jul 2002 at 16:42 (+0200), Volker Kroll wrote:
Vielen Dank, Ihr habt mir wirklich weitergeholfen. Ich hoffe, ich nerve mit derartig trivialen Fragen nicht!
Nein, ganz im Gegenteil. Irgendwie bin ich beruhigt, dass andere an den gleichen Stellen Schwierigkeiten haben. Außerdem hat das dazu geführt, dass ich heute mal wieder etwas in C programmiert habe, was ich sonst nicht getan hätte (momentan bin ich auf dem PHP-Trip).
PS: Bernhard: Sagtest Du nicht, daß Du auch Anfänger in C bist?
Ja.
Habe ich vielleicht ein gutes Buch übersehen? Ich habe bisher Kernighan - Ritchie und Stevens: Advanced programming in an unix environment gelesen.
Ich habe bisher nur "C für Linux in 21 Tagen (M&T)" gelesen. Auf jeden Fall ein gutes Buch, allerdings kann man die ersten paar Tage ziemlich schnell überfliegen, wenn man bereits andere Sprachen kennt. Siehe auch http://www.bwalle.de/buecher.shtml. Außerdem habe ich noch "C kurz&gut (O'Reilly)". Wahrscheinlich liegt es einfach daran, dass man immer einfacher die Fehler eines anderen findet als die eigenen. Viel Ahnung von C habe ich nicht -- die Lösungen von Philipp Thomas sind sicher besser. Dein Buch geht sicher sehr auf alle Details ein.
So langsam beginne ich auch die Zusammenhänge zu verstehen, aber gerade Pointer und Pointerarithmetik sind mir noch sehr fremd, da es das in den anderen Sprachen, die ich bisher benutzt habe, nicht gab.
So ging/geht es mir auch. In Perl, Bash, PHP gibt's solche Probleme einfach nicht. Andererseits ist das Objekte-Zeug von Java auch nicht gerade besonders einfach. Irgendwie hat jede Sprache so ihre Tücken. ;-) Gruß, Bernhard -- _________ http://www.bwalle.de _________________________________________________ Der elektronische Marktplatz wird unsere Kultur ebenso verändern wie Gutenbergs Druckerpresse die Welt des Mittelalters. -- Bill Gates
On Thu, 18 Jul 2002 at 16:29 (+0200), Philipp Thomas wrote:
#include
#include void tester(char **t) { *t = "langer string"; }
int main (int argc, char* argv[]) { char *field = "teststring"; tester(&field); printf("String: %s\n", field); return 0; }
Aber Vorsicht, das geht nur mit Stringkonstanten gut! Wären die Strings dynamisch alloziert hättest du da ein prima Speicherleck.
Warum? Könntest Du / ein anderer das etwas näher (für Anfänger wie mich) erläutern? Was heißt "Speicherleck"? Gruß, Bernhard -- _________ http://www.bwalle.de _________________________________________________ Wußten Sie, daß 85% aller Statistiken falsch sind?
Bernhard Walle wrote:
Warum? Könntest Du / ein anderer das etwas näher (für Anfänger wie mich) erläutern? Was heißt "Speicherleck"?
http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/buffer-overflo... Peter
Peter Wiersig wrote:
Bernhard Walle wrote:
Warum? Könntest Du / ein anderer das etwas näher (für Anfänger wie mich) erläutern? Was heißt "Speicherleck"?
Es geht reservierter Speicher "verloren": Man benutzt ihn nicht mehr, gibt ihn aber auch nicht wieder frei. Um das in das Beispiel einzubauen, sagen wir mal, main() legt den String in dynamisch reservierten Speicher und übergibt dann den Pointer darauf an tester(): [...] char *field = strdup("teststring"); tester(&field); [...] Nun überschreibt die Funktion tester() den Pointer mit einem anderen Wert, nämlich den Pointer auf einen neuen String: void tester(char **t) { *t = strdup("langer string"); } Dann ist der ursprüngliche Wert des Pointers field weg, denn field zeigt jetzt ja auf den von tester() mit strdup() neu angelegten Speicherbereich. Damit ist der von main() mit strdup() angelegte Speicherbereich nicht mehr ansprechbar, aber -- er wurde ja nicht freigegeben -- weiterhin reserviert. Wenn sich solche Sachen häufen und das Programm länger läuft, dann wird der Speicherbedarf des Prozesses mit der Zeit ganz schön groß... Abhilfe könnte man z.B. schaffen, indem tester() den alten Speicherbereich erst freigibt: void tester(char **t) { free(*t); *t = strdup("langer string"); } Das ist dann im Endeffekt so ähnlich wie Deine Variante mit realloc(), nur daß der neue Speicherbereich ruhig eine andere Anfangsadresse als der alte haben kann. Bei einer solchen Lösung darf *t aber keinesfalls ein Zeiger auf eine String-Konstante sein, denn die kann man natürlich nicht freigeben.
http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/buffer-overflo...
Nein, Pufferüberläufe sind etwas anderes als Speicherlecks. Bei einem Pufferüberlauf geht kein reservierter Speicher verloren, sondern es wird über die Grenzen eines zu kleinen Speicherbereichs hinaus geschrieben -- die möglichen Folgen sind im allgemeinen nicht gerade harmloser... Eilert -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Eilert Brinkmann -- Universitaet Bremen -- FB 3, Informatik eilert@informatik.uni-bremen.de - eilert@tzi.org http://www.informatik.uni-bremen.de/~eilert/
On Thu, 18 Jul 2002 at 17:29 (+0200), Peter Wiersig wrote:
Bernhard Walle wrote:
Warum? Könntest Du / ein anderer das etwas näher (für Anfänger wie mich) erläutern? Was heißt "Speicherleck"?
http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/buffer-overflo...
Was hat jetzt ein "Speicherleck" mit einem Buffer Overflow zu tun? Nach http://www.wikiservice.at/dse/wiki.cgi?MemoryLeak ist ein Speicherleck einfach "verlorener" Speicher, der nicht freigegeben wurde und nicht mehr freigegeben werden kann. Jetzt verstehe ich auch, was Philipp meinte und den anderen Vorschlag. Was ich nicht verstehe: Was hat das mit Sicherheitsproblemen zu tun? Wie kann damit ein Buffer Overflow erzeugt werden? Gruß, Bernhard -- _________ http://www.bwalle.de _________________________________________________ Das Telefon hat zu viele ernsthaft zu bedenkende Mängel für ein Kommunikationsmittel. Das Gerät ist von Natur aus von keinem Wert für uns. -- »Western Union«, Interne Meldung (1876)
Bernhard Walle
Was ich nicht verstehe: Was hat das mit Sicherheitsproblemen zu tun?
Gar nichts :)
Wie kann damit ein Buffer Overflow erzeugt werden?
Überhaupt nicht. Speicherlecks und Pufferüberläufe haben rein gar nichts mit einander zu tun. Philipp -- Philipp Thomas work: pthomas@suse.de Development SuSE Linux AG private: philippt@t-online.de
Bernhard Walle wrote:
Was hat jetzt ein "Speicherleck" mit einem Buffer Overflow zu tun?
Nichts.
Was ich nicht verstehe: Was hat das mit Sicherheitsproblemen zu tun?
Meist sieht man Speicherlecks (ganz anders als Pufferüberläufe) zwar nicht so sehr als Sicherheitsproblem, aber auch da kann es einen Zusammenhang geben. Ein Speicherleck kann zu massivem Auslagern oder sogar zum Aufbrauchen des gesamten virtuellen Speichers führen und dadurch ein System lahmlegen. Bei hinreichend restriktivem ulimit wird nur der betroffene Prozeß abgebrochen. Beides kann zu einem (zumindest teilweisen) Denial of Service führen. Eilert -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Eilert Brinkmann -- Universitaet Bremen -- FB 3, Informatik eilert@informatik.uni-bremen.de - eilert@tzi.org http://www.informatik.uni-bremen.de/~eilert/
Bernhard Walle
Warum? Könntest Du / ein anderer das etwas näher (für Anfänger wie mich) erläutern? Was heißt "Speicherleck"?
Speicherlecks sind Speicher, der alloziert aber nicht freigegeben
werden kann, da die Adresse unbekannt ist:
char *t;
t = malloc(50);
t = malloc(100);
Nach dem zweiten Aufruf von malloc() sind 50 Bytes vom Programm
alloziert, können aber nicht mehr freigegeben werden, da t ja nun auf
einen neu angeforderten Speicherbereich verweist. Folgendes
Testprogramm:
#include
On Fri, 19 Jul 2002 at 02:41 (+0200), Philipp Thomas wrote:
[Speicherlecks]
Danke für die ausführlichen Erläuterungen!
Der obige Fall ist ja noch schnell erkennbar, aber in komplexeren Programmen kann es durchaus vorkommen, dass man den Überblick verliert und dann kann z.B. ein Speicherleck im X-Server den ganzen Rechner praktisch zu Stillstand bringen, weil er nur noch mit Swappen beschäftigt ist.
<ot> Könnte es vielleicht sein, dass YOU von SuSE 7.2 so ein Speicherleck hat? Immerhin läuft bei einem Online-Update bei mir der ganze Speicher inkl. Swap (also mindestens 200 MB) (fast) voll. </ot> Gruß, Bernhard -- _________ http://www.bwalle.de _________________________________________________ Unser Zeitalter ist stolz auf Maschinen die denken und mißtrauisch gegen Menschen, die es versuchen. -- (unbekannt)
Hi! Am Fre, 2002-07-19 um 09.50 schrieb Bernhard Walle:
<ot> Könnte es vielleicht sein, dass YOU von SuSE 7.2 so ein Speicherleck hat? Immerhin läuft bei einem Online-Update bei mir der ganze Speicher inkl. Swap (also mindestens 200 MB) (fast) voll. </ot>
Bei meiner SuSE 7.2 sieht das nicht aus wie ein Speicherleck, da der Speicher hinterher wieder freigegeben wird (jedenfalls nach top und Gefühl, ausgemessen habe ich das jetzt nicht). Aus eigener Erfahrung würde das Speicherleck-Szenario für YOU nach fünfmaligem Starten dafür sorgen, dass von meinen Speicher nix mehr da ist, meine Festplatte aus dem swappen gar nicht mehr rauskommt und das System sich dann wohl aufhängt. :) CU Martin
Martin Oehler wrote:
Am Fre, 2002-07-19 um 09.50 schrieb Bernhard Walle:
<ot> Könnte es vielleicht sein, dass YOU von SuSE 7.2 so ein Speicherleck hat? Immerhin läuft bei einem Online-Update bei mir der ganze Speicher inkl. Swap (also mindestens 200 MB) (fast) voll. </ot>
Bei meiner SuSE 7.2 sieht das nicht aus wie ein Speicherleck, da der Speicher hinterher wieder freigegeben wird (jedenfalls nach top und Gefühl, ausgemessen habe ich das jetzt nicht).
Das ist kein Widerspruch. Der von einem Prozeß belegte Speicher wird bei Prozeßende vom System wieder freigegeben, auch wenn er von dem Programm selbst vergessen wurde. Insofern beschränkt sich der Effekt nur auf die Laufzeit des Prozesses (bzw. etwas darüber hinaus, bis das System wieder aufgeräumt hat). Allerdings können während dieser Zeit z.T. extreme Folgestörungen[1] verursacht werden. Auch ein dauerhaftes Problem entsteht natürlich, wenn ein Speicherleck nicht in einem normalen Programm, sondern im Kernel vorliegt. Eilert Footnotes: [1] Andere Prozesse können nicht mehr richtig arbeiten bzw. werden vom Kernel (mitunter auch noch einigermaßen willkürlich) zur Behebung des allgemeinen Speichermangels beendet. Das tollste, was ich in der Hinsicht mal erlebt habe, war, daß der Kernel (weiß leider die genaue Version nicht mehr) dabei auch den init-Prozeß getötet hat... -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Eilert Brinkmann -- Universitaet Bremen -- FB 3, Informatik eilert@informatik.uni-bremen.de - eilert@tzi.org http://www.informatik.uni-bremen.de/~eilert/
Hi! Am Fre, 2002-07-19 um 12.19 schrieb Eilert Brinkmann:
Das ist kein Widerspruch. Der von einem Prozeß belegte Speicher wird bei Prozeßende vom System wieder freigegeben, auch wenn er von dem Programm selbst vergessen wurde. Insofern beschränkt sich der Effekt nur auf die Laufzeit des Prozesses (bzw. etwas darüber hinaus, bis das System wieder aufgeräumt hat).
Oh ja, aber auf die garbage collection würde ich mich nicht verlassen. Gerade wenn die Software keine durchgängige Ausnahmebehandlung hat ist das kritisch. Dies trifft oft Listen-oder Baumstrukturen, die nicht mit STL-Containern angelegt wurden, sondern quasi per Hand (mal als Beispiel). Ich weiss nicht, ob es an meinem Kernel liegt (2.4.16), aber ich habe keine Probleme, meinen verfügbaren Hauptspeicher MB-weise mit selbstgeschriebener Software zu verkleinern. Um das ganze richtig sauber zu betreiben, sollte man eigentlich in einem catch-Block (Existenz vorausgesetzt) nicht nur die exception weiter werfen, sondern auch noch seine Ressourcen freigeben, sofern notwendig. Interessante und sehr einfache Beispiele hierzu finden sich z.B. im Stroustrup. CU Martin
Am Fre, 2002-07-19 um 11.00 schrieb Martin Oehler:
Hi!
Am Fre, 2002-07-19 um 09.50 schrieb Bernhard Walle:
<ot> Könnte es vielleicht sein, dass YOU von SuSE 7.2 so ein Speicherleck hat? Immerhin läuft bei einem Online-Update bei mir der ganze Speicher inkl. Swap (also mindestens 200 MB) (fast) voll. </ot>
Aus eigener Erfahrung würde das Speicherleck-Szenario für YOU nach fünfmaligem Starten dafür sorgen, dass von meinen Speicher nix mehr da ist, meine Festplatte aus dem swappen gar nicht mehr rauskommt und das System sich dann wohl aufhängt. :) Nein, die hier diskutierte Variante von Memory-Leaks wirkt sich nur bei Programmen aus, die _dauerhaft_ laufen, wie z.B. Daemons, da Programme jeglichen Speicher beim Beenden wieder freigeben.
Ralf
Hi! Am Sam, 2002-07-20 um 09.41 schrieb Ralf Corsepius:
Am Fre, 2002-07-19 um 11.00 schrieb Martin Oehler:
Aus eigener Erfahrung würde das Speicherleck-Szenario für YOU nach fünfmaligem Starten dafür sorgen, dass von meinen Speicher nix mehr da ist, meine Festplatte aus dem swappen gar nicht mehr rauskommt und das System sich dann wohl aufhängt. :)
Nein, die hier diskutierte Variante von Memory-Leaks wirkt sich nur bei Programmen aus, die _dauerhaft_ laufen, wie z.B. Daemons, da Programme jeglichen Speicher beim Beenden wieder freigeben.
Ich bin eigentlich davon ausgegangen, dass man YOU (und yast2) wieder beendet. Ich zeige mal ein Beispiel auf für ein memory leak, wie ich eines meinte: (vielleicht wird dann klarer, was ich oben geschrieben habe) vorher: -------
free total used free shared buffers cached Mem: 1545840 92884 1452956 0 5720 43328 -/+ buffers/cache: 43836 1502004 Swap: 1694848 41776 1653072
Programm läuft: ---------------
free total used free shared buffers cached Mem: 1545840 1515944 29896 0 10064 62424 -/+ buffers/cache: 1443456 102384 Swap: 1694848 812344 882504
hinterher: (3,4,...,10 Min) ----------
free total used free shared buffers cached Mem: 1545840 215084 1330756 0 35320 97292 -/+ buffers/cache: 82472 1463368 Swap: 1694848 0 1694848
Den Speicher kriege ich zur Laufzeit nicht mehr. Und das wird nach jedem Ausführen weniger. Ob das Programm zur Laufzeit soviel Speicher brauchen sollte, steht auf einem anderen Blatt... Egal, obiges paarmal gemacht, und schon steht mein Rechner. CU Martin
Am Sam, 2002-07-20 um 11.32 schrieb Martin Oehler:
Hi!
Am Sam, 2002-07-20 um 09.41 schrieb Ralf Corsepius:
Am Fre, 2002-07-19 um 11.00 schrieb Martin Oehler:
Aus eigener Erfahrung würde das Speicherleck-Szenario für YOU nach fünfmaligem Starten dafür sorgen, dass von meinen Speicher nix mehr da ist, meine Festplatte aus dem swappen gar nicht mehr rauskommt und das System sich dann wohl aufhängt. :)
Nein, die hier diskutierte Variante von Memory-Leaks wirkt sich nur bei Programmen aus, die _dauerhaft_ laufen, wie z.B. Daemons, da Programme jeglichen Speicher beim Beenden wieder freigeben.
Ich bin eigentlich davon ausgegangen, dass man YOU (und yast2) wieder beendet. Es könnte sein, dass wir aneinander vorbeireden.
Ich sprach lediglich davon, dass die Art der Memory-Leaks, die hier diskutiert wird, keine persistenten Memory-Leaks produzieren darf, da "normal" (d.h. statisch, automatisch und dynamisch) allokierter Speicher immer beim Beenden eines Programms freigegeben wird, egal wie defekt die Applikation sein mag. D.h. nicht, dass YOU nicht fehlerhaft sein mag und persistente Memory-Leaks produziert, es heisst lediglich, dass ich deinen Schluss für nicht stimmig halte. Persistente Memory-Leaks könnten z.B. durch * Treiber-Bugs ... * Zombies (Prozesse, die sich nicht sauber beenden) oder geforkte Prozesse die beim Tod nicht sauber beendet werden ... * Bugs im Kernel-Memory-Management + SYSV-Shared-Mem. u.s.w. entstehen. Doch selbst wenn nach Beendigung eines Prozesses Speicher nicht sofort wieder freigegeben wird, muss dass noch lange nicht heissen, dass "der Speicher persistent leckt" - Es kann sein, dass sich im Hintergrund irgendetwas verändert hat, irgendetwas dynamisch nachgeladen worden sein, aber noch nicht wieder freizugeben worden sein (z.B. könnte ein Kernel-Module nachgeladen worden sein und noch "herumhängen", es könnten Daemons gestartet worden sein, die vorher nicht liefen (z.B. irgendwelche Sounddaemons), es könnten Caches gefüllte worden sein, die vorher nicht gefüllt waren (z.B. squid), usw. usf.).
Ich zeige mal ein Beispiel auf für ein memory leak, wie ich eines meinte: (vielleicht wird dann klarer, was ich oben geschrieben habe)
vorher: -------
free total used free shared buffers cached Mem: 1545840 92884 1452956 0 5720 43328 -/+ buffers/cache: 43836 1502004 Swap: 1694848 41776 1653072
Programm läuft: ---------------
free total used free shared buffers cached Mem: 1545840 1515944 29896 0 10064 62424 -/+ buffers/cache: 1443456 102384 Swap: 1694848 812344 882504
hinterher: (3,4,...,10 Min) ----------
free total used free shared buffers cached Mem: 1545840 215084 1330756 0 35320 97292 -/+ buffers/cache: 82472 1463368 Swap: 1694848 0 1694848 Damit das eine Aussagekraft hat, müsstest Du auch beobachten, welcher Prozess vor und nachher, wieviel Speicher benutzt hat.
Den Speicher kriege ich zur Laufzeit nicht mehr. Und das wird nach jedem Ausführen weniger. Ob das Programm zur Laufzeit soviel Speicher brauchen sollte, steht auf einem anderen Blatt... Egal, obiges paarmal gemacht, und schon steht mein Rechner. Welcher Kernel?
Genau so sehen auch die Symptome des Swap/Memory-Management-Problems mit Kerneln ca. < 2.4.10 aus. Ralf
Hi, Ralf! Am Sam, 2002-07-20 um 12.26 schrieb Ralf Corsepius:
Am Sam, 2002-07-20 um 11.32 schrieb Martin Oehler:
Es könnte sein, dass wir aneinander vorbeireden.
Hehe, wenn ich nochmal drüberlese, mindestens ein bißchen :)
Ich sprach lediglich davon, dass die Art der Memory-Leaks, die hier diskutiert wird, keine persistenten Memory-Leaks produzieren darf, da "normal" (d.h. statisch, automatisch und dynamisch) allokierter Speicher immer beim Beenden eines Programms freigegeben wird, egal wie defekt die Applikation sein mag.
Damit hast Du ja auch recht. Jedenfalls sollte es so sein. Ich wollte jedoch nur ausdrücklich davor warnen, sich darauf zu verlassen (im Hinterkopf hatte ich die Beispielapplikation). Die frisst natürlich keinen Speicher mehr nach dem Beenden, unterscheidet sich damit auch grundsätzlich von einem defekten demon.
D.h. nicht, dass YOU nicht fehlerhaft sein mag und persistente Memory-Leaks produziert, es heisst lediglich, dass ich deinen Schluss für nicht stimmig halte.
Um YOU ging es mir gar nicht so sehr...s.o., y2bignfat hat seinen Namen wahrscheinlich nicht zufällig ;)
Persistente Memory-Leaks könnten z.B. durch * Treiber-Bugs ... * Zombies (Prozesse, die sich nicht sauber beenden) oder geforkte Prozesse die beim Tod nicht sauber beendet werden ... * Bugs im Kernel-Memory-Management + SYSV-Shared-Mem. u.s.w. entstehen.
ja
Doch selbst wenn nach Beendigung eines Prozesses Speicher nicht sofort wieder freigegeben wird, muss dass noch lange nicht heissen, dass "der Speicher persistent leckt" - Es kann sein, dass sich im Hintergrund irgendetwas verändert hat, irgendetwas dynamisch nachgeladen worden sein, aber noch nicht wieder freizugeben worden sein (z.B. könnte ein Kernel-Module nachgeladen worden sein und noch "herumhängen", es könnten Daemons gestartet worden sein, die vorher nicht liefen (z.B. irgendwelche Sounddaemons), es könnten Caches gefüllte worden sein, die vorher nicht gefüllt waren (z.B. squid), usw. usf.).
Jo, das meinte ich, s.o. [Beispiel rausgenommen]
Damit das eine Aussagekraft hat, müsstest Du auch beobachten, welcher Prozess vor und nachher, wieviel Speicher benutzt hat.
Das passt schon um die Qualität (oder sollte ich sagen den Horror) des Problems zu bewerten, hier machts die Erfahrung mit dem Verhalten der SW, an der man seit Jahren arbeitet.
Den Speicher kriege ich zur Laufzeit nicht mehr. Und das wird nach jedem Ausführen weniger. Ob das Programm zur Laufzeit soviel Speicher brauchen sollte, steht auf einem anderen Blatt... Egal, obiges paarmal gemacht, und schon steht mein Rechner.
Welcher Kernel?
2.4.16 original SuSE
Genau so sehen auch die Symptome des Swap/Memory-Management-Problems mit Kerneln ca. < 2.4.10 aus.
Ich will dem Kernel jetzt mal nicht die Schuld geben, meine Probleme habe ich auf verschiedenen (2.4.18 usw.) Kerneln. Das ist alles nicht so einfach, da das eine größtenteils mathematische Anwendung ist mit teilweise ziemlich wilden Datenstrukturen. Alles auch noch HW-beschleunigt (nvidia-Treiber), teilweise parallel (PVM) und die graphic engine ist auch neu. Da kriegt man leicht bugs, die das System nicht mehr fängt. Gerade die nvidia-Treiber sind auch nicht gerade (je nach Version) unproblematisch. Soviel zur Praxis. :) Ich denke, wir sind uns einig. Oder? CU Martin
Hallo, Bernhard Walle:
<ot> Könnte es vielleicht sein, dass YOU von SuSE 7.2 so ein Speicherleck hat? Immerhin läuft bei einem Online-Update bei mir der ganze Speicher inkl. Swap (also mindestens 200 MB) (fast) voll. </ot>
Dann kommst du "billig" weg. Ich habe meinem Server ein temporäres swapfile von 1 GB verpasst, um YOUen zu können. Gruß, Ratti -- http://www.gesindel.de/neu/ | Fontlinge | Die Schriftenverwaltung für LINUX
Am Donnerstag, 18. Juli 2002 14:24 schrieb Volker Kroll:
noch mal eine dumme Frage. Wenn ich einer Funktion einen Pointer übergebe, sollte diese doch den Inhalt des Pointers ändern können. Warum funktioniert dann diese
Nö, Du kannst den Speicherbereich ändern, auf den der Pointer verweist, Du kriegst aber nur eine Kopie des Pointers selbst übergeben.
Funktion nicht: #include
void tester(char*); int main (int argc, char* argv[]) { char *field = "teststring";
Irgendwo im Speicher werden 11 Byte reserviert (sagen wir mal 0x100), dort wird "teststring\0" abgelegt und der char-Pointer verweist darauf (in dem Fall enthält er also 0x100).
tester(field);
Funktion Tester wird aufgerufen, übergeben wird 0x100.
printf("String: %s\n", field);
Field ist unverändert und enthält nach wie vor 0x100, der Text an der Stelle wird ausgegeben und dürfte "teststring" sein.
/* prints teststring not langer String */ return 0;
}
Hier gehts wie folgt ab:
void tester(char* test) {
0x100 wurde übergeben.
test = "langer String";
Ein neuer Speicherbereich wird allociert 14 Byte lang mit Inhalt "langer String\0", sagen wir mal direkt dahinter an 0x10c, 'test' enthält nun 0x10c, was auf 'field' nicht den geringsten Einfluss hat.
}
Mögliche Lösungen: 1. Du gibst test als Returnwert zurück und übernimmst diesen in field. 2. Du übergibst nen Pointer auf field (char **) und kannst dann das feld selbst modifizieren. -- Machs gut | http://www.iiv.de/schwinde/buerger/tremmel/ Manfred | http://www.knightsoft-net.de
Moin,
Eine Sache noch:
* Volker Kroll
void tester(char* test) { test = "langer String"; }
Ich würde mich nicht darauf verlassen, daß der String "langer String" nach dem Verlassen der Funktion noch vorhanden ist. Thorsten -- Unix is not an 'A-ha!' experience, it is more of a 'Holy shit!' experience. - Colin McFadyen
Moin,
* Thorsten Haude
* Volker Kroll
[02-07-18 14:24]: void tester(char* test) { test = "langer String"; }
Ich würde mich nicht darauf verlassen, daß der String "langer String" nach dem Verlassen der Funktion noch vorhanden ist.
Unsinn, es war zu spät gestern. Thorsten -- They that can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety. - Benjamin Franklin
participants (11)
-
Bernhard Walle
-
Daniel Bauer / MList
-
Eilert Brinkmann
-
Manfred Tremmel
-
Martin Oehler
-
Peter Wiersig
-
Philipp Thomas
-
Ralf Corsepius
-
Ratti
-
Thorsten Haude
-
Volker Kroll