Warum programmiert ihr in C und was?
-
Warum programmiert ihr in C und was für Programme macht ihr so mit C?
-
Ich programmiere nicht in C.
Früher aber einige Programme unter Linux angepasst, wenn es für die Projekte erforderlich war.
-
Na um den stack oder heap anderer Leute zu crashen. Was sonst?
-
C benutze ich eigentlich nur aus Übungszwecken. Am liebsten Übungen wo man intensiv mit Pointern rumfummeln muss. Sowas wie Treiber schreiben hab ich noch nie getan, vmtl. mal ein Einstieg wert.
Ansonsten benutz ich C++ ist einfach viel bequemer.
-
Ich glaube mal gelesen zu haben, dass man diese Speicherfehler in einem C Programm viel leichter findet als in einem C++ Programm. Kann das jemand bestätigen?
Gibt es nicht auch genug C++ Software die unsicher hinsichtlich Speichermanagement ist?
-
CFrager schrieb:
Ich glaube mal gelesen zu haben, dass man diese Speicherfehler in einem C Programm viel leichter findet als in einem C++ Programm. Kann das jemand bestätigen?
Gibt es nicht auch genug C++ Software die unsicher hinsichtlich Speichermanagement ist?
In C++ hat man keine Speicherfehler.
-
volkard schrieb:
In C++ hat man keine Speicherfehler.
Hat man in C auch nicht.
-
Bitte beim Thema bleiben und kein C vs C++ anfangen. Zum darauf Herumhacken gibt es Java :p
-
Java im Magen, C im Herzen.
-
CFrager schrieb:
Ich glaube mal gelesen zu haben, dass man diese Speicherfehler in einem C Programm viel leichter findet als in einem C++ Programm. Kann das jemand bestätigen?
C ist sehr viel fehleranfälliger für Speicherfehler! C++ bietet dir RAII, was, wenn du es richtig benutzt, einen Speicherfehler ich sag mal nahezu unmöglich macht.
-
begeistert schrieb:
C ist sehr viel fehleranfälliger für Speicherfehler! C++ bietet dir RAII, was, wenn du es richtig benutzt, einen Speicherfehler ich sag mal nahezu unmöglich macht.
Wenn du C beherrscht und sorgfältig programmierst ist auch C recht sicher.
-
begeistert schrieb:
C ist sehr viel fehleranfälliger für Speicherfehler!
Huh?
Die beiden Sprachen stehen sich da kaum in etwas nach. C++ nimmt dir nur einen riesigen Batzen ab, das bezahlst du dann mit höherer Abstraktion. Dafür kannst du dann in C Sachen machen, über die jeder C++-Programmierer die Nase rümpft, weil sie's nicht machen dürfen (Moment - ich dachte, C++ wäre eine Erweiterung Cs?) und neidisch sind. :p
begeistert schrieb:
C++ bietet dir RAII, was, wenn du es richtig benutzt, einen Speicherfehler ich sag mal nahezu unmöglich macht.
Wieso sollte ich ein Objekt initialisieren, dass ich nie verwende? Bei C habe ich die Wahl, ein Objekt auf dem Stack auch einfach vergammeln zu lassen. Die Wahl habe ich in C++ nicht, hier wird garantiert einmal ein Konstruktor und der Destruktor aufgerufen.
"Dann verwende lieber einen Zeiger auf das Objekt."? Dann habe ich noch einmal zusätzlich
new / delete
drin. Nicht unbedingt langsam, aber einfach komplett unnötig.Ich habe eine bessere Idee: wir nehmen einfach
_init
- und_free
-Funktionen für einen Typ, und die musste manuell aufrufen. Wer_init
sagt, muss auch_free
sagen.
-
dachschaden schrieb:
Die Wahl habe ich in C++ nicht, hier wird garantiert einmal ein Konstruktor und der Destruktor aufgerufen.
struct foo { int bar; }; int main() { foo f; }
Welchen Wert hat
f.bar
?
-
Swordfish schrieb:
struct foo { int bar; }; int main() { foo f; }
Welchen Wert hat
f.bar
?Undefiniert, weil in C++ der Standard-Konstruktor nix macht. Ich glaube allerdings, du hast meine Kritik nicht verstanden.
Die von dir angegebene Struktur macht nichts kompliziertes. Nimm aber stattdessen eine Struktur, die einen Zeiger hält, mit der ich arbeiten will.
Gerade habe ich so was hier rumfliegen - eine Mapping-Struktur, die Speicher vom OS Seitenweise anfordert. Ihrerseits hält diese ein Objekt, welches die Adresse und die Länge des Mappings speichert. Der "Destruktor" (der von mir vorgeschlagene
_free
-Aufruf) gibt diesen Speicher wieder an das OS zurück. Bedingt durch die besondere Art, wie Speicher auf Windows funktioniert (mremap
ist nicht vorhanden), muss ich auch ohne je Speicher reserviert zu haben eine Tabelle anlegen, in der ich Informationen über fortlaufende Speicherbereiche halte.Sagen wir, ich greife auf das Mapping nur dann zu, wenn Parameter X == NULL ist (ist sogar genau das, was der Code hier tut). Das kann heißen, dass das Objekt über die komplette Funktion immer mal wieder verwendet wird, nicht in einem fortlaufenden Block, aber immer in Blöcken, in denen sichergestellt wurde, dass X == NULL ist. In all den Blöcken, in denen X != NULL ist, wird stattdessen was anderes gemacht, was das Mapping-Objekt nicht anfasst.
Dadurch, dass das Objekt für die komplette Funktion verfügbar ist, würde ein Konstruktor bereits durch Funktionseintritt aufgerufen werden. Lebenszyklus von Objekten, sofern ich das nicht falsch verstanden habe. Dadurch habe ich dann automatisch beim Funktionseintritt und -Austritt jeweils einen Syscall sitzen, selbst wenn ich das Objekt gar nicht verwende.
In C kann ich im ersten X == NULL-Block
_init
machen, das Objekt initialisieren - und dann auch garantierterweise verwenden. Und im letzten X == NULL-Block kann ich_free
machen. Kein Automatismus macht, was er eventuell nicht soll.In C++ wird bereits zum Funktionseintritt das Objekt erstellt, die Tabelle angelegt, und dann wieder freigegeben, obwohl ich sie eventuell gar nicht gebraucht habe.
Und wenn ich das Anlegen der Tabelle in eine eigene Funktion packe, dann kann ich RAII auch gleich in die Tonne kloppen. Denn diese eigene Funktion habe ich in C bereits - siehe
_init
. Soll ich das auch gleich für C++ so bauen, dass die Tabelle nicht mit dem Konstruktoraufruf erstellt wird? Kann ich machen - und RAII auch wieder ad absurdum führen.RAII ist ein Sicherheitskonzept für blöde Programmierer, die sich nicht sicher sind, wann ein Objekt initialisiert ist. Ja, klar, kann man machen. ich will damit nur nichts zu tun haben.
-
dachschaden schrieb:
Sagen wir, ich greife auf das Mapping nur dann zu, wenn Parameter X == NULL ist (ist sogar genau das, was der Code hier tut). Das kann heißen, dass das Objekt über die komplette Funktion immer mal wieder verwendet wird, nicht in einem fortlaufenden Block, aber immer in Blöcken, in denen sichergestellt wurde, dass X == NULL ist. In all den Blöcken, in denen X != NULL ist, wird stattdessen was anderes gemacht, was das Mapping-Objekt nicht anfasst.
Klingt mir eher danach, als wär deine Codestruktur Schwachsinn...
-
dot schrieb:
Klingt mir eher danach, als wär deine Codestruktur Schwachsinn...
Eben nicht. Sie war großer Schwachsinn, bevor ich diese Funktionalität zusammengelegt habe. So musste jede Funktion, die die beschriebene Funktion aufrufen wollte, nicht erst prüfen, ob X != NULL ist, um dann eine andere Funktion aufzurufen.
Ich habe das bereits hinter mir, ich kenne den anderen Weg, und er ist Scheiße.
-
Habe ich das jetzt richtig verstanden, dass Speicherfehler in C und C++ möglich sind, dies aber vom Können des Programmierer abhängt?
-
CFrager schrieb:
Habe ich das jetzt richtig verstanden, dass Speicherfehler in C und C++ möglich sind, dies aber vom Können des Programmierer abhängt?
Ja.
-
dachschaden schrieb:
Swordfish schrieb:
struct foo { int bar; }; int main() { foo f; }
Welchen Wert hat
f.bar
?Undefiniert, weil in C++ der Standard-Konstruktor nix macht. Ich glaube allerdings, du hast meine Kritik nicht verstanden.
Ich glaub eher, mich hat deine allgemeine Aussage gestört. (... und wer regt sich ernsthaft über einen ctor aus, der effektiv nop ist)
-
Swordfish schrieb:
(... und wer regt sich ernsthaft über einen ctor aus, der effektiv nop ist)
Jemand der C++ nicht wirklich verstanden hat oder sich weigert, es zu versuchen...