Warum C / C ++ Speicherprobleme haben?

8

Ich habe viele Programmierer gelesen und geschrieben, wenn es in C / C ++ programmiert wird, gibt es viele Probleme im Zusammenhang mit dem Speicher. Ich plane zu lernen, in C / C ++ zu programmieren. Ich habe Anfängerkenntnisse in C / C ++ und möchte ein kurzes Beispiel sehen, warum C / C ++ Probleme mit der Speicherverwaltung haben kann. Bitte stellen Sie einige Beispiele zur Verfügung.

    
LinuxNewbie 05.06.2010, 06:17
quelle

9 Antworten

16

Es gibt viele Möglichkeiten, den Speicher in C oder C ++ zu beschädigen oder zu verlieren. Diese Fehler gehören zu den am schwierigsten zu diagnostizierenden Fehlern, da sie oft nicht leicht reproduzierbar sind.

Es ist beispielsweise einfach, den von Ihnen zugewiesenen Speicher nicht freizugeben. Zum Beispiel wird dies ein "doppelt frei" machen, indem versucht wird, a zweimal zu befreien und b nicht zu befreien:

%Vor%

Ein Beispiel für einen Pufferüberlauf, der willkürlichen Speicher verdirbt, folgt. Es ist ein Pufferüberlauf, weil Sie nicht wissen, wie lange str ist. Wenn es länger als 256 Bytes ist, dann schreibt es diese Bytes irgendwo in den Speicher, möglicherweise überschreiben Sie Ihren Code, möglicherweise nicht.

%Vor%     
fmark 05.06.2010, 23:31
quelle
7

Grundsätzlich müssen Sie in diesen Sprachen jedes Speicherbit manuell anfordern, das zur Kompilierungszeit keine lokale Variable ist, und Sie müssen es manuell freigeben, wenn Sie es nicht mehr benötigen. Es sind Bibliotheken (sog. Smartpointer), die diesen Prozess bis zu einem gewissen Grad automatisieren können, aber nicht überall anwendbar sind. Darüber hinaus gibt es absolut keine Grenzen dafür, wie Sie mit der Zeigerarithmetik auf den Speicher zugreifen können (versuchen).

Die manuelle Speicherverwaltung kann zu einer Reihe von Fehlern führen:

  • Wenn Sie vergessen, Speicher freizugeben, haben Sie ein Speicherleck
  • Wenn Sie mehr Speicher verwenden, als Sie für einen bestimmten Zeiger angefordert haben, haben Sie einen Pufferüberlauf.
  • Wenn Sie Speicher freigeben und weiterhin einen "dangling pointer" verwenden, haben Sie ein undefiniertes Verhalten (normalerweise stürzt das Programm ab)
  • Wenn Sie Ihre Zeigerarithmetik falsch berechnen, haben Sie einen Absturz oder beschädigte Daten

Und viele dieser Probleme sind sehr schwer zu diagnostizieren und zu debuggen.

    
Michael Borgwardt 05.06.2010 06:31
quelle
5
  

Ich plane, in C / C ++ zu programmieren

Was genau meinst du damit? Möchten Sie lernen, in C zu programmieren, oder möchten Sie lernen, in C ++ zu programmieren? Ich würde nicht empfehlen, beide Sprachen gleichzeitig zu lernen.

Aus der Sicht des Benutzers ist die Speicherverwaltung in C ++ viel einfacher als in C, da das meiste davon in Klassen eingekapselt ist, zum Beispiel std::vector<T> . Aus konzeptioneller Sicht ist die Speicherverwaltung von C sehr viel einfacher. Grundsätzlich gibt es nur malloc und free :)

    
fredoverflow 05.06.2010 07:00
quelle
5

Ich kann ehrlich sagen, dass ich bei der Programmierung in C ++ keine "Probleme" mit der Speicherzuweisung habe. Das letzte Mal, dass ich ein Speicherleck hatte, war vor über 10 Jahren, und war wegen Blindheit meinerseits. Wenn Sie Code unter Verwendung von RAII, Standardbibliothekscontainern und einem kleinen Maß an gesundem Menschenverstand schreiben, existiert das Problem wirklich nicht.

    
anon 05.06.2010 08:14
quelle
3

Der Grund dafür, dass dies in C / C ++ häufig als etwas bezeichnet wird, ist, dass viele moderne Sprachen Speicherverwaltung und Speicherbereinigung durchführen. In C / C ++ ist dies nicht der Fall (zum Guten oder zum Schlechten). Sie müssen Speicher manuell zuordnen und freigeben, und wenn dies nicht ordnungsgemäß durchgeführt wird, führt dies zu einem Speicherverlust, der in einer Sprache, die die Speicherverwaltung für Sie übernimmt, nicht möglich wäre.

    
VeeArr 05.06.2010 06:21
quelle
3

Eines der üblichen Speicherverwaltungsprobleme in C und C ++ hängt mit dem Fehlen von Grenzen zusammen, die auf Arrays überprüft werden. Im Gegensatz zu Java (zum Beispiel) überprüfen C und C ++ nicht, um sicherzustellen, dass der Array-Index innerhalb der tatsächlichen Array-Grenzen liegt. Aus diesem Grund ist es leicht, Speicher versehentlich zu überschreiben. Zum Beispiel (C ++):

%Vor%

Mit dem obigen Code wird kein Kompilierungs- oder Laufzeitfehler verbunden sein, außer dass Ihr Code Speicher überschreibt, der nicht sein sollte.

    
Greg Hewgill 05.06.2010 06:25
quelle
2
___ answer2979492 ___
  

Ich plane, in C / C ++ zu programmieren

Was genau meinst du damit? Möchten Sie lernen, in C zu programmieren, oder möchten Sie lernen, in C ++ zu programmieren? Ich würde nicht empfehlen, beide Sprachen gleichzeitig zu lernen.

Aus der Sicht des Benutzers ist die Speicherverwaltung in C ++ viel einfacher als in C, da das meiste davon in Klassen eingekapselt ist, zum Beispiel %code% . Aus konzeptioneller Sicht ist die Speicherverwaltung von C sehr viel einfacher. Grundsätzlich gibt es nur %code% und %code% :)

    
___ qstntxt ___

Ich habe viele Programmierer gelesen und geschrieben, wenn es in C / C ++ programmiert wird, gibt es viele Probleme im Zusammenhang mit dem Speicher. Ich plane zu lernen, in C / C ++ zu programmieren. Ich habe Anfängerkenntnisse in C / C ++ und möchte ein kurzes Beispiel sehen, warum C / C ++ Probleme mit der Speicherverwaltung haben kann. Bitte stellen Sie einige Beispiele zur Verfügung.

    
___ answer2979430 ___

Es gibt viele Möglichkeiten, den Speicher in C oder C ++ zu beschädigen oder zu verlieren. Diese Fehler gehören zu den am schwierigsten zu diagnostizierenden Fehlern, da sie oft nicht leicht reproduzierbar sind.

Es ist beispielsweise einfach, den von Ihnen zugewiesenen Speicher nicht freizugeben. Zum Beispiel wird dies ein "doppelt frei" machen, indem versucht wird, %code% zweimal zu befreien und %code% nicht zu befreien:

%Vor%

Ein Beispiel für einen Pufferüberlauf, der willkürlichen Speicher verdirbt, folgt. Es ist ein Pufferüberlauf, weil Sie nicht wissen, wie lange %code% ist. Wenn es länger als 256 Bytes ist, dann schreibt es diese Bytes irgendwo in den Speicher, möglicherweise überschreiben Sie Ihren Code, möglicherweise nicht.

%Vor%     
___ qstnhdr ___ Warum C / C ++ Speicherprobleme haben? ___ answer2979665 ___

Ich kann ehrlich sagen, dass ich bei der Programmierung in C ++ keine "Probleme" mit der Speicherzuweisung habe. Das letzte Mal, dass ich ein Speicherleck hatte, war vor über 10 Jahren, und war wegen Blindheit meinerseits. Wenn Sie Code unter Verwendung von RAII, Standardbibliothekscontainern und einem kleinen Maß an gesundem Menschenverstand schreiben, existiert das Problem wirklich nicht.

    
___ answer2979404 ___

Der Grund dafür, dass dies in C / C ++ häufig als etwas bezeichnet wird, ist, dass viele moderne Sprachen Speicherverwaltung und Speicherbereinigung durchführen. In C / C ++ ist dies nicht der Fall (zum Guten oder zum Schlechten). Sie müssen Speicher manuell zuordnen und freigeben, und wenn dies nicht ordnungsgemäß durchgeführt wird, führt dies zu einem Speicherverlust, der in einer Sprache, die die Speicherverwaltung für Sie übernimmt, nicht möglich wäre.

    
___ answer2979427 ___

Grundsätzlich müssen Sie in diesen Sprachen jedes Speicherbit manuell anfordern, das zur Kompilierungszeit keine lokale Variable ist, und Sie müssen es manuell freigeben, wenn Sie es nicht mehr benötigen. Es sind Bibliotheken (sog. Smartpointer), die diesen Prozess bis zu einem gewissen Grad automatisieren können, aber nicht überall anwendbar sind. Darüber hinaus gibt es absolut keine Grenzen dafür, wie Sie mit der Zeigerarithmetik auf den Speicher zugreifen können (versuchen).

Die manuelle Speicherverwaltung kann zu einer Reihe von Fehlern führen:

  • Wenn Sie vergessen, Speicher freizugeben, haben Sie ein Speicherleck
  • Wenn Sie mehr Speicher verwenden, als Sie für einen bestimmten Zeiger angefordert haben, haben Sie einen Pufferüberlauf.
  • Wenn Sie Speicher freigeben und weiterhin einen "dangling pointer" verwenden, haben Sie ein undefiniertes Verhalten (normalerweise stürzt das Programm ab)
  • Wenn Sie Ihre Zeigerarithmetik falsch berechnen, haben Sie einen Absturz oder beschädigte Daten

Und viele dieser Probleme sind sehr schwer zu diagnostizieren und zu debuggen.

    
___ answer3002957 ___

Es ist offensichtlich, dass Sie den Speicher freigeben müssen, der nicht mehr verwendet wird oder in Zukunft nicht mehr verwendet wird, aber Sie müssen am Anfang des Programms feststellen, dass der Speicherbedarf statisch ist oder variiert, wenn er ausgeführt wird. Wenn es dynamisch ist, nehmen Sie genug Speicher für Ihre Programmarbeit, dass Ihr Programm möglicherweise zusätzlichen Speicher verbraucht.

Sie müssen also den Speicher freigeben, der nicht verwendet wird, und diese Zeit erstellen, wenn sie benötigt wird. genau wie

%Vor%

Hier nehme ich 100 Schüler in der Klasse an. Student kann mehr als 100 oder weniger 100. Wenn mehr als 100, dann wird Ihr Programm Informationen verlieren oder weniger 100 dann Programm wird ausgeführt, aber die Verschwendung von Speicher, kann es groß sein.

Daher erstellen wir normalerweise zum Zeitpunkt der Ausführung einen Datensatz dynamisch. genau wie

%Vor%

Wenn nicht verwendet, lösche es aus dem Raum.

%Vor%

Das ist eine gute Methode zum Programmieren, wenn Sie nicht aus dem Speicher entfernen, dann kann es auf einmal Ihren Speicherstapel füllen und es kann hängen.

    
___ answer2979411 ___

Eines der üblichen Speicherverwaltungsprobleme in C und C ++ hängt mit dem Fehlen von Grenzen zusammen, die auf Arrays überprüft werden. Im Gegensatz zu Java (zum Beispiel) überprüfen C und C ++ nicht, um sicherzustellen, dass der Array-Index innerhalb der tatsächlichen Array-Grenzen liegt. Aus diesem Grund ist es leicht, Speicher versehentlich zu überschreiben. Zum Beispiel (C ++):

%Vor%

Mit dem obigen Code wird kein Kompilierungs- oder Laufzeitfehler verbunden sein, außer dass Ihr Code Speicher überschreibt, der nicht sein sollte.

    
___ answer2979543 ​​___

Wenn ein neuer Speicherblock verwendet wird, ist die vom Betriebssystem reservierte Größe möglicherweise größer als Ihre Anforderung, aber niemals kleiner. Aus diesem Grund und der Tatsache, dass delete nicht sofort den Speicher an das Betriebssystem zurückgibt, wenn Sie den gesamten Speicher untersuchen, den Ihr Programm verwendet, können Sie glauben gemacht werden, dass Ihre Anwendung schwerwiegende Speicherlecks aufweist. Die Überprüfung der Anzahl der Bytes, die das gesamte Programm verwendet, sollte daher nicht zur Erkennung von Speicherfehlern verwendet werden. Nur wenn der Speichermanager ein großes und kontinuierliches Speicherwachstum anzeigt, sollten Sie Speicherlecks vermuten.

    
___ tag123c ___ C ist eine universelle Computerprogrammiersprache, die für Betriebssysteme, Bibliotheken, Spiele und andere Hochleistungsanwendungen verwendet wird. Dieses Tag sollte bei allgemeinen Fragen zur C-Sprache verwendet werden, wie in der Norm ISO 9899: 2011 definiert. Fügen Sie ggf. ein versionsspezifisches Tag wie c99 oder c90 für Fragen zu älteren Sprachstandards hinzu. C unterscheidet sich von C ++ und es sollte nicht mit dem C ++ - Tag kombiniert werden, wenn ein rationaler Grund fehlt. ___ answer2980028 ___

Eine Sache, die bisher noch nicht erwähnt wurde, ist die Leistung und warum Sie Speicher manuell verwalten möchten. Das Verwalten von Speicher ist schwierig, insbesondere, wenn ein Programm komplexer wird (insbesondere wenn Sie Threads verwenden und wenn die Lebensdauer von Speicherstücken komplex wird (dh wenn es schwierig wird, wenn Sie es nicht genau sagen können, wenn Sie kein Stück benötigen) von Informationen)) sogar mit leistungsfähigen modernen Programmierwerkzeugen wie Valgrind.

Warum sollten Sie den Speicher manuell verwalten wollen, ein paar Gründe: - Um zu verstehen, wie es funktioniert / zu - Um Garbage Collection / automatische Speicherverwaltung zu implementieren, müssen Sie manuell - Bei etwas niedrigeren Level-Dingen wie einem Kernel braucht man die Flexibilität, die manuelle Steuerung des Speichers geben kann. - Am wichtigsten, wenn Sie manuelle Speicherverwaltung richtig machen, können Sie eine große Beschleunigung / geringeren Speicheraufwand (bessere Leistung), ein damit verbundenes Problem mit Garbage Collection (obwohl es besser als bessere Garbage Collectors wie der Hotspot jvm wird geschrieben) ist, dass Sie die Speicherverwaltung nicht kontrollieren können, so dass es schwer ist, Dinge in Echtzeit zu erledigen (Fristen für bestimmte Ziele wie Autobremsen und Schrittmacher zu garantieren) und Programme, die mit Benutzern interagieren, könnten ein wenig einfrieren oder Verzögerung (das würde für ein Spiel lutschen).

Viele "moderne C ++" (es wurde gesagt, dass C ++ kann als mehrere Sprachen gedacht werden, je nachdem, wie Sie es verwenden) im Gegensatz zu c mit Klassen (oder X-und C ++ -Funktion) verwenden Sie häufig einen Kompromiss Verwenden Sie einfach optional GC / automatische Speicherverwaltung (beachten Sie, dass optional GC kann bei der Speicherverwaltung dann obligatorisch sein, da, wenn es obligatorisch ist ein einfacheres System) Funktionen und und einige manuelle Speicherverwaltung. Abhängig davon, wie Sie dies tun, kann es einige Vorteile und Nachteile der Verwendung von GC und manuelle Speicherverwaltung haben. Optional GC ist auch mit einigen C-Bibliotheken verfügbar, aber es ist weniger üblich mit c als C ++.

    
___ tag123memo ___ hilf uns dieses Wiki zu bearbeiten ___ tag123c ___ C ++ ist eine universelle Programmiersprache. Es wurde ursprünglich als Erweiterung von C entworfen und behält eine ähnliche Syntax, ist aber jetzt eine komplett andere Sprache. Verwenden Sie dieses Tag für Fragen zu Code, der mit einem C ++ - Compiler kompiliert werden soll. ___ tag123memorymanagement ___ Prozess des dynamischen Zuweisens und Freigebens von Teilen des physischen Speichers, um auf Programmanforderungen mit, wenn möglich, Fairness und ohne Verhungern unter den Anforderern zu antworten. ___
Rupeshit 05.06.2010 07:25
quelle
2

Es ist offensichtlich, dass Sie den Speicher freigeben müssen, der nicht mehr verwendet wird oder in Zukunft nicht mehr verwendet wird, aber Sie müssen am Anfang des Programms feststellen, dass der Speicherbedarf statisch ist oder variiert, wenn er ausgeführt wird. Wenn es dynamisch ist, nehmen Sie genug Speicher für Ihre Programmarbeit, dass Ihr Programm möglicherweise zusätzlichen Speicher verbraucht.

Sie müssen also den Speicher freigeben, der nicht verwendet wird, und diese Zeit erstellen, wenn sie benötigt wird. genau wie

%Vor%

Hier nehme ich 100 Schüler in der Klasse an. Student kann mehr als 100 oder weniger 100. Wenn mehr als 100, dann wird Ihr Programm Informationen verlieren oder weniger 100 dann Programm wird ausgeführt, aber die Verschwendung von Speicher, kann es groß sein.

Daher erstellen wir normalerweise zum Zeitpunkt der Ausführung einen Datensatz dynamisch. genau wie

%Vor%

Wenn nicht verwendet, lösche es aus dem Raum.

%Vor%

Das ist eine gute Methode zum Programmieren, wenn Sie nicht aus dem Speicher entfernen, dann kann es auf einmal Ihren Speicherstapel füllen und es kann hängen.

    
userBI 09.06.2010 03:42
quelle
1

Eine Sache, die bisher noch nicht erwähnt wurde, ist die Leistung und warum Sie Speicher manuell verwalten möchten. Das Verwalten von Speicher ist schwierig, insbesondere, wenn ein Programm komplexer wird (insbesondere wenn Sie Threads verwenden und wenn die Lebensdauer von Speicherstücken komplex wird (dh wenn es schwierig wird, wenn Sie es nicht genau sagen können, wenn Sie kein Stück benötigen) von Informationen)) sogar mit leistungsfähigen modernen Programmierwerkzeugen wie Valgrind.

Warum sollten Sie den Speicher manuell verwalten wollen, ein paar Gründe: - Um zu verstehen, wie es funktioniert / zu - Um Garbage Collection / automatische Speicherverwaltung zu implementieren, müssen Sie manuell - Bei etwas niedrigeren Level-Dingen wie einem Kernel braucht man die Flexibilität, die manuelle Steuerung des Speichers geben kann. - Am wichtigsten, wenn Sie manuelle Speicherverwaltung richtig machen, können Sie eine große Beschleunigung / geringeren Speicheraufwand (bessere Leistung), ein damit verbundenes Problem mit Garbage Collection (obwohl es besser als bessere Garbage Collectors wie der Hotspot jvm wird geschrieben) ist, dass Sie die Speicherverwaltung nicht kontrollieren können, so dass es schwer ist, Dinge in Echtzeit zu erledigen (Fristen für bestimmte Ziele wie Autobremsen und Schrittmacher zu garantieren) und Programme, die mit Benutzern interagieren, könnten ein wenig einfrieren oder Verzögerung (das würde für ein Spiel lutschen).

Viele "moderne C ++" (es wurde gesagt, dass C ++ kann als mehrere Sprachen gedacht werden, je nachdem, wie Sie es verwenden) im Gegensatz zu c mit Klassen (oder X-und C ++ -Funktion) verwenden Sie häufig einen Kompromiss Verwenden Sie einfach optional GC / automatische Speicherverwaltung (beachten Sie, dass optional GC kann bei der Speicherverwaltung dann obligatorisch sein, da, wenn es obligatorisch ist ein einfacheres System) Funktionen und und einige manuelle Speicherverwaltung. Abhängig davon, wie Sie dies tun, kann es einige Vorteile und Nachteile der Verwendung von GC und manuelle Speicherverwaltung haben. Optional GC ist auch mit einigen C-Bibliotheken verfügbar, aber es ist weniger üblich mit c als C ++.

    
Roman A. Taycher 05.06.2010 10:56
quelle

Tags und Links