Jemand hat mir gesagt, dass die Zuordnung mit malloc nicht mehr sicher ist, ich bin kein C / C ++ - Guru, aber ich habe einige Sachen mit malloc und C / C ++ gemacht. Weiß jemand, über welche Risiken ich spreche?
Zitiert ihn:
[..] Aber in der Tat ist der Schwachpunkt von C / C ++ die Sicherheit, und die Achillesferse ist tatsächlich malloc und der Missbrauch von Zeigern. C / C ++ ist eine bekannte unsichere Sprache. [..] Es würde einige Apps geben, die ich nicht empfehlen würde, mit C ++ weiter zu programmieren. "
[...] C / C ++ ist eine bekannte unsichere Sprache. [...]
Eigentlich ist das falsch. Eigentlich gibt es "C / C ++" gar nicht. Es gibt C und es gibt < em> C ++ . Sie teilen einige (oder, wenn Sie wollen, viele) Syntax, aber sie sind tatsächlich sehr verschiedene Sprachen .
Eine Sache, in der sie sich sehr unterscheiden, ist ihre Art, dynamisches Gedächtnis zu verwalten. Die C-Methode verwendet tatsächlich malloc()
/ free()
und wenn Sie dynamischen Speicher benötigen, gibt es sehr wenig anderes, was Sie tun können, als sie zu verwenden (oder ein paar Geschwister von malloc()
).
C ++ Weg ist nicht zu (manuell) Umgang mit dynamischen Ressourcen (von denen Speicher ist aber eins) überhaupt . Das Ressourcenmanagement wird an einige gut implementierte und getestete Klassen, vorzugsweise aus der Standardbibliothek, übergeben und dann automatisch ausgeführt. Zum Beispiel gibt es std::string
, anstatt manuell mit Null-terminierten Zeichenpuffern umzugehen, anstatt manuell mit dynamisch zugewiesenen Arrays umzugehen, dort std:vector
, anstatt manuell mit offenen Dateien zu arbeiten, gibt es die std::fstream
Familie von Streams etc .
Es stimmt wahrscheinlich, dass C ++ new
sicherer ist als malloc()
, aber das macht malloc()
nicht automatisch unsicherer als zuvor. Hat dein Freund gesagt, warum er es für unsicher hält?
1) Bei C ++ müssen Sie vorsichtig sein, wenn Sie malloc()
/ free()
und new
/ delete
Seite-an-Seite im selben Programm. Dies ist möglich und zulässig, aber alles, was mit malloc()
zugewiesen wurde, muss mit free()
und nicht mit delete
freigegeben werden. Ebenso muss alles, was mit new
zugewiesen wurde, mit delete
und niemals mit free()
freigegeben werden. (Diese Logik geht noch weiter: Wenn Sie ein Array mit new[]
zuweisen, müssen Sie es mit delete[]
und nicht nur mit delete
freigeben.) Verwenden Sie immer entsprechende Gegenstücke für die Zuordnung und Freigabe pro Objekt.
2) malloc()
und new
(was wiederum von C ++ spricht) machen nicht genau dasselbe. malloc()
gibt Ihnen nur einen Teil des zu verwendenden Speicherplatzes; new
wird zusätzlich einen Konstruktor aufrufen (falls verfügbar). Auf ähnliche Weise ruft delete
einen Destruktor auf (falls verfügbar), während free()
dies nicht tut. Dies könnte zu Problemen führen, wie zum Beispiel falsch initialisierte Objekte (weil der Konstruktor nicht aufgerufen wurde) oder nicht freigegebene Ressourcen (weil der Destruktor nicht aufgerufen wurde).
3) C ++% new
kümmert sich auch um Zuweisung der richtigen Menge an Speicher für den angegebenen Typ, während Sie dies mit malloc()
selbst berechnen müssen:
In C ++ sollte new
/ delete
möglichst vor malloc()
/ free()
stehen. (In C ist new
/ delete
nicht verfügbar, daher wäre die Auswahl dort offensichtlich.)
Ihr Freund könnte darüber sprechen:
Die Sicherheit der Verwendung von Zeigern im Allgemeinen. Wenn Sie beispielsweise in C ++ ein Array von Zeichen mit malloc zuweisen, fragen Sie, warum Sie nicht string
oder vector
verwenden. Zeiger sind nicht unsicher, aber Code, der wegen der falschen Verwendung von Zeigern fehlerhaft ist.
Etwas über malloc im Besonderen. Die meisten Betriebssysteme löschen Speicher, bevor sie aus Sicherheitsgründen zuerst an einen Prozess übergeben werden. Sonst könnten vertrauliche Daten von einer App an eine andere App weitergegeben werden. Auf Betriebssystemen, die das nicht tun, könnten Sie argumentieren, dass es eine mit malloc
verbundene Unsicherheit gibt. Es ist wirklich mehr mit free
verbunden.
Es ist auch möglich, dass dein Freund nicht weiß, wovon er spricht. Wenn jemand sagt "X ist unsicher", lautet meine Antwort: "In welcher Weise?".
Vielleicht ist Ihr Freund älter, und er ist nicht vertraut mit dem, wie die Dinge jetzt funktionieren - ich dachte C und C ++ waren im Grunde gleich, bis ich viele neue Dinge über die Sprache entdeckte, die in den letzten 10 Jahren entstanden sind ( Die meisten meiner Lehrer waren Bell-Typen aus der alten Schule, die hauptsächlich in C geschrieben waren und nur oberflächliche Kenntnisse von C ++ hatten - und die Ingenieure von Bell Laboratories erfanden C ++! Lachen Sie nicht über ihn / sie - Sie könnten auch eines Tages dort sein!
Ich denke, dein Freund ist unbehaglich mit der Idee, dass du deine eigene Speicherverwaltung machen musst - dh es ist leicht, Fehler zu machen. In dieser Hinsicht ist es unsicher und er / sie hat Recht ... Dieser unsichere Aspekt kann jedoch durch gute Programmierpraktiken überwunden werden, wie z -Raii-oder-warum-Sie-Sie-nie-müssen-Sie-sich-noch-Ressourcen-Management-noch einmal /> RAII und mit Smart-Zeigern.
Für viele Anwendungen ist eine automatische Speicherbereinigung jedoch wahrscheinlich in Ordnung, und einige Programmierer sind verwirrt darüber, wie Zeiger funktionieren, so dass es für neue, unerfahrene Entwickler schwierig sein kann, in C / C ++ ohne etwas Training effektiv zu programmieren. Welches ist vielleicht, warum dein Freund denkt, dass C / C ++ vermieden werden sollte.
Dies ist die einzige Möglichkeit, Speicher in C nativ zuzuweisen und freizugeben. Wenn Sie es missbrauchen, kann es genauso unsicher sein wie alles andere. Microsoft bietet einige "sichere" Versionen anderer Funktionen an, die einen zusätzlichen size_t-Parameter benötigen - vielleicht bezog sich Ihr Freund auf etwas Ähnliches? Wenn das der Fall ist, bevorzugt er vielleicht calloc () gegenüber malloc ()?
Wenn Sie C verwenden, müssen Sie malloc
verwenden, um Speicher zuzuweisen, es sei denn, Sie haben eine Bibliothek eines Drittanbieters, die Ihren Speicher für Sie reserviert / verwaltet.
Sicherlich hat Ihr Freund einen Punkt, dass es schwierig ist, sicheren Code in C zu schreiben, besonders wenn Sie Speicher reservieren und mit Puffern umgehen. Aber wir alle wissen das, oder? :)
Was er dich vielleicht warnen wollte, ist die Verwendung von Zeigern. Ja, das wird Probleme verursachen, wenn Sie nicht verstehen, wie es funktioniert. Ansonsten frag, was dein Freund gemeint hat, oder frage ihn nach einer Referenz, die seine Bestätigung beweist.
Zu sagen, dass malloc
nicht sicher ist, ist so, als würde man sagen "benutze das System X nicht, weil es unsicher ist".
Bis dahin verwenden Sie malloc
in C und new
in C ++.
Wenn Sie malloc
in C ++ verwenden, werden die Leute verrückt nach Ihnen sein, aber das ist in sehr speziellen Fällen gut.
Mit Malloc als solcher ist nichts falsch. Dein Freund meint offenbar, dass manuelles Speichermanagement unsicher ist und leicht zu Fehlern führt. Im Vergleich zu anderen Sprachen, in denen der Speicher automatisch von einem Garbage Collector verwaltet wird (nicht dass es keine Lecks gibt), kümmert es niemanden, ob das Programm bei der Beendigung des Programms aufräumt läuft).
Natürlich würde man in malloc gar nicht wirklich malloc anfassen (weil es einfach nicht funktional äquivalent zu neu ist und einfach nicht das tut, was man braucht, die meiste Zeit vorausgesetzt will nicht nur rohe Erinnerung bekommen). Darüber hinaus ist es vollständig möglich, mit Techniken zu programmieren, die die Möglichkeit von Speicherlecks und Korruption (RAII) fast vollständig eliminieren, aber dafür braucht man Erfahrung.
Technisch gesehen war malloc
anfangs nie sicher, aber abgesehen davon ist das einzige, was mir einfällt, der berüchtigte "OOM-Killer" (OOM = out-of-memory), den der Linux-Kernel verwendet. Sie können darauf nachlesen wenn Sie wollen. Ansonsten sehe ich nicht, wie malloc
selbst inhärent unsicher ist.
Es ist nicht sicher, malloc zu verwenden, da es nicht möglich ist, eine groß angelegte Anwendung zu schreiben und sicherzustellen, dass jedes malloc effizient freigegeben wird. Daher werden Sie viele Speicherlecks haben, die ein Problem darstellen können oder auch nicht ... aber , wenn Sie free
verdoppeln oder das falsche delete
etc verwenden, kann undefiniertes Verhalten zur Folge haben. Tatsächlich erlaubt die Verwendung des falschen delete
in C ++ in der Regel die Ausführung beliebigen Codes.
Die ONLY Möglichkeit für Code, der in einer Sprache wie C oder C ++ geschrieben ist, um sicher zu sein, besteht darin, das gesamte Programm mit seinen Abhängigkeiten mathematisch nachzuweisen.
Moderne memory-safe Sprachen sind vor diesen Arten von Fehlern sicher, solange die zugrundeliegende Sprachimplementierung nicht verwundbar ist (was wirklich selten ist, weil diese alle in C / C ++ geschrieben sind, aber während wir uns auf Hardware-JVMs zubewegen Problem wird weggehen).