Ich habe vor kurzem mit C angefangen, da ich mir einen Raspberry Pi
zugelegt habe.
Kompiliert wird das mit gcc.
Bisher hatte ich mit c# zu tun.
Ich habe vor ein Programm zu schreiben, das lange laufen soll. Jetzt hat
c# ja das Speichermanagement und C nicht.
Was gibt es bei C zu beachten, damit nicht irgendwann wegen
Speicherüberlauf oder ähnlichem das Programm abstürzt?
Nathan Palke schrieb:> Was gibt es bei C zu beachten, damit nicht irgendwann wegen> Speicherüberlauf oder ähnlichem das Programm abstürzt?
Nichts dynamisch allokieren, was du nicht dynamisch allokieren musst.
Alles was du dynamisch allokierst, musst du selber auch wieder
freigeben, wenn du es nicht mehr brauchst.
Und ein Rat in eigener Sache: ein bischen strukturiert arbeiten und den
Modulgedanken beherzigen und du bist auf dem richtigen Weg.
Ansonsten: leg dir ein C Buch zu. Die Unterschiede zwischen C# und C
sind größer, als einfach nur ein # im Namen. C# hat mehr mit Java zu tun
als mit C.
Speicherüberlauf passiert, wenn du z.B. Objekte anlegst aber nicht mehr
frei gibst. Das kannst Du sicherer machen, wenn man Referenzzählung
benützt.
Du musst dir halt Gedanken darüber machen, wann was angelegt wird und
wann man was wieder freigeben muss, weil es nicht mehr gebraucht wird.
Wenn man auf eine dynamische Speicherbelegung verzichtet, dann passiert
das auch nicht. Unendlich Speicher hat man aber auch nicht.
Einfach nicht zu kompliziert machen und verstehen was man macht bzw. was
passiert. Ois ganz easy!
Bei C# kann man aüch so seine Fehler machen. Wenn Objekte sich
gegeneinander halten, aber nicht mehr gebraucht werden, dann hat man
auch ein Problem.
mario schrieb:> Wenn Objekte sich> gegeneinander halten, aber nicht mehr gebraucht werden, dann hat man> auch ein Problem.
C# verwendet da doch kein einfaches refcounting, eher was
Mark&Sweep-Artiges welches solche zyklen erkennt und abräumt.
Dr. Sommer schrieb:> mario schrieb:>> Wenn Objekte sich>> gegeneinander halten, aber nicht mehr gebraucht werden, dann hat man>> auch ein Problem.> C# verwendet da doch kein einfaches refcounting, eher was> Mark&Sweep-Artiges welches solche zyklen erkennt und abräumt.
Was aber leider memory leaks trotzdem nicht unmöglich sondern nur
leichter vermeidbar macht.
Dr. Sommer schrieb:> Nathan Palke schrieb:>> Gib doch mal ein paar Beispiele für>> - dynamisch allokieren> malloc () odervoid someFunc () {> int num = ...;> int array [num];> }> - wieder freigeben> free ()
Ich habe etwa diese Funktion
Dr. Sommer schrieb:> Aaargh. Du solltest dringend mal C lernen anstatt wild irgendeinen> Unsinn zu fragen. Am besten mit einem Buch.
Paß auf deinen Ton auf.
Nathan Palke schrieb:> Paß auf deinen Ton auf.
Pass du auf deine Umweltbelästigung, äh, Fragen, auf. Niemand hat Lust
dem 1.000.000.000'sten C-Anfänger zu erläutern dass man nicht einfach
lustig frei nach Try&Error so anfangen kann irgendwelchen Code zu
schreiben und auszuprobieren "weil man ja schon C# kann und 'if'&'while'
funktionieren ja überall gleich", sondern sich fundiert einlesen muss um
die Grundlagen zu verstehen. Hier die Tausendste Erläuterung vom
C-Speicher-Management extra für dich zu schreiben ist mir meine Tastatur
zu schade. Lies wie alle anderen ein Buch, und wenn du etwas ganz
konkretes bestimmtes nicht verstehst darfst du fragen. -> Netiquette
Dr. Sommer schrieb:> Nathan Palke schrieb:>> Paß auf deinen Ton auf.> Pass du auf deine ...
Das wars, weder habe ich weitergelesen noch werde ich dich in Zukunft
ernstnehmen.
Nathan Palke schrieb:> Geht das also nur mit Variablen mit einem * davor?
Bevor du hier eine Frage zu Speichermanagement in C stellst, solltest du
wissen, was ein "*" vor einem Namen bedeutet. Dann kannst du dich
wieder melden.
Dr. Sommer schrieb:> ... C lernen anstatt wild irgendeinen Unsinn zu fragen.
Ack
Nathan Palke schrieb:> Dr. Sommer schrieb:>> Aaargh. Du solltest dringend mal C lernen anstatt wild irgendeinen>> Unsinn zu fragen. Am besten mit einem Buch.>> Paß auf deinen Ton auf.
Er hat aber recht.
Karl Heinz Buchegger schrieb:> Nathan Palke schrieb:>> Dr. Sommer schrieb:>>> Aaargh. Du solltest dringend mal C lernen anstatt wild irgendeinen>>> Unsinn zu fragen. Am besten mit einem Buch.>>>> Paß auf deinen Ton auf.>> Er hat aber recht.
Mag inhaltlich sein, in dem Ton aber nicht.
Ich habe es oft genug erlebt, daß Menschen wegen einer Kleinigkeit das
Einarbeiten empfehlen. Mit Kanonen auf Spatzen zu schießen ist en vogue.
Schaue ich es mir dann genauer an, ist es stets eine Zeile Code und
schon funktioniert es.
Daher reagiere ich auf den Standardspruch "Les dich ein" sehr
allergisch.
Erkläre mir einfach in respektvollem Ton - wie DU es bisher ja
hinbekommen hast - was ich für mein Ziel wissen muß.
Ich fange nicht von Null, sondern jahrelanger Erfahrung mit c# an.
Beantworte also einfach, was ich wissen muß um das Programm nicht nach
Tagen abstürzen zu sehen, wenn ich es unbeobachtet lasse. Setze Wissen
über C# voraus, das wird das Ganze um einiges verkürzen.
Und empfehle mir bitte nicht wie alle anderen, mit Kanonen auf Spatzen
zu schießen. Danke.
Nathan Palke schrieb:>> Erkläre mir einfach in respektvollem Ton - wie DU es bisher ja> hinbekommen hast - was ich für mein Ziel wissen muß.
Sorry.
Ich erklär dir hier ganz sicher nicht Dinge, die in jedem halbwegs
anständigen C-Buch mindestens 1/4 des kompletten Buchumfangs ausmachen.
> Ich fange nicht von Null,
doch. Du fängst bei 0 an.
> sondern jahrelanger Erfahrung mit c# an.
Die ist herzlich uninteressant. Das was du da mitbringst, ist in den
ersten 20 Seiten deines C-Buchs behandelt. Die restlichen 180 Seiten
sind für dich komplettes Neuland.
Das fängt bei Arrays an, geht über Zeiger und Argument Passing zu
Strings und landet bei ca. der Buchmitte in der dynamischen
Speicherverwaltung. Mal das Kapitel Files ausgenommen, wird es dann ab
dort richtig heavy.
> Setze Wissen über C# voraus, das wird das Ganze um einiges verkürzen.
Das wird überhaupt nichts verkürzen. Eher im Gegenteil.
Und wenn du dir bei Amazon schon ein C-Buch holst, kauf dir auch gleich
noch was über Datenstrukturen mit dazu. dynamische Arrays, Listen
(einfach und doppelt verkettet), Bäume, Hash-Tables und der ganze Kram.
Warst du es bisher gewohnt im Auto den Zündschlüssel umzudrehen und die
Automatik auf 'Drive' zu stellen, so sitzt du jetzt selber an den
Kontrollen. Du stellst selber deinen Zündzeitpunkt und die
Einspritzanlage ein, überwachst die Lambda-Sonde, regelst das Gemisch
nach und ziehst die Reifen auf die Felgen auf. Das gibt dir große Power
in allen Fahrsituationen, erfordert aber auch dass man es von der Pieke
auf lernt.
Das Sicherheitsnetz C# existiert nicht mehr. Du hast die volle Kontrolle
über die Maschine. Da gibt es keine Mami mehr, die hinter dir aufräumt.
Mit der Tante Lulu gehen war gestern - jetzt bist du selber gefragt.
> Das wird überhaupt nichts verkürzen. Eher im Gegenteil.
Das kann ich leider nur bestätigen.
Ich hab mit C/C++ gelernt (was nicht heißt das ich die Sprache bis ins
kleinste detail kenne) und durfte dann auch mal ein Programm in C#
schreiben, der zweck heiligt halt die Mittel. C# ist, salop gesagt,
pille palle im vergleich zu C/C++, weil du vieles nicht siehst bzw. dir
von der Sprache abgenommen wird.
Wenn du nicht weißt was ein Zeiger ist, was ein Zeiger macht und wie ein
Zeiger Funktioniert kommst du nicht an einem Buch vorbei, da helfen auch
keine ach so tollen online tutorials, wo man denkt man hat alles nach 5
Minuten verstanden. In solchen Tutorials wird dir grob erklärt wie man
was macht, aber nicht was es für auswirkungen haben kann und worauf man
achten muss.
Muss nicht mal ein teures 1000-Seiten Buch sein, C/C++ für Dummies tuts
auch. Nur weil die Bücher "... für Dummies" heißen, will ich hier
niemanden als Deppen verkaufen. Die Bücher sind aber sehr einfach
gehalten, anschaulich beschrieben und leicht verständlich.
1
staticvoid*funktion(void*ptr)
2
{
3
FILE*status;
4
free(status)
5
}
Da fängt es schon an, das free macht keinen Sinn, da Du den Zeiger nicht
dynamisch anlegst.
Die Regeln sind ganz einfach:
hast du ein malloc() brauchst du auch ein free(),
hast du ein new brauchst du auch ein delete.
free/delete ohne malloc/new --> unfug,
malloc/new ohne free/delete --> memory leaks!
Ist wirklich nicht böse gemeint, aber an dieser Stelle solltest du
selbst einsehen: Kauf dir ein Buch!
Und ich sehe das kommen, was an so einer stelle immer von
Jave/C#-Erfahrenen kommt: C/C++ ist ja totaler mist, und Pointer sind ja
sooo gefährlich.
Und ich sage: Ja, auch eine Bastelschere für 3-Jährige Kinder ist
gefährlich wenn du nicht weißt was du da machst!
In diesem Sinne, schönes Wochenende, werd jetzt auch mit meinen RPi
spielen gehen :)
MfG Kaj
Kaj schrieb:> Die Regeln sind ganz einfach:> hast du ein malloc() brauchst du auch ein free(),> hast du ein new brauchst du auch ein delete.> free/delete ohne malloc/new --> unfug,> malloc/new ohne free/delete --> memory leaks!
:-)
Ja, das sind die Basisregeln (nicht das ich da jetzt widersprechen
würde). Aber über die Implikationen und was daraus folgt und was das für
die Anwendung bedeutet und wie man die Dinge einsetzt, organisiert und
kombiniert, darüber kann man wieder eigene ganze Bücher schreiben. Und
nicht nur eines. Nicht umsonst hatte ich im Studium 2 Semester lang eine
Vorlesung namens "Datenstrukturen" samt Übungen.
Es ist wie Schach. Man kann die Regeln auf einer halben DIN-A4 Seite
zusammenfassen und die auswendig lernen. Aber spielen kann man deswegen
noch lange nicht.
> Und ich sehe das kommen, was an so einer stelle immer von> Jave/C#-Erfahrenen kommt: C/C++ ist ja totaler mist, und Pointer sind ja> sooo gefährlich.> Und ich sage: Ja, auch eine Bastelschere für 3-Jährige Kinder ist> gefährlich wenn du nicht weißt was du da machst!
Das ist ein schöner Vergleich. Muss ich mir merken. Denn das trifft den
Nagel auf den Kopf.
Mit /unsafe kommt auch in C# etwas C++-Feeling auf.
Und wenn man bei IDisposable Klassen das Dispose() vergisst, hat man oft
ähnliche Effekte wie bei einem fehlenden free() in C.
Nathan Palke schrieb:> Ich fange nicht von Null, sondern jahrelanger Erfahrung mit c# an.> Beantworte also einfach, was ich wissen muß um das Programm nicht nach> Tagen abstürzen zu sehen, wenn ich es unbeobachtet lasse. Setze Wissen> über C# voraus, das wird das Ganze um einiges verkürzen.
Du bist ein Architekt, der tolle Fertighäuser aus Standardkomponenten
planen kann. Und jetzt stehst du in der afrikanischen Steppe, vor einem
Berg Lehm, wasser, und Stroh, und willst mit deinem Wissen daraus ein
Haus bauen.
Ja, du kannst C# programmieren, aber die fehlen sämtliche handwerklichen
Grundlagen in C. Vor der Frage nach der Vermeidung von Memoryleaks kommt
erst einmal die Erarbeitung des Verständnisses, wie man überhaupt
Memoryleaks erzeugt ;)
Oliver
Karl Heinz Buchegger schrieb:> Nathan Palke schrieb:>>> Was gibt es bei C zu beachten, damit nicht irgendwann wegen>> Speicherüberlauf oder ähnlichem das Programm abstürzt?>> Nichts dynamisch allokieren, was du nicht dynamisch allokieren musst.> Alles was du dynamisch allokierst, musst du selber auch wieder> freigeben, wenn du es nicht mehr brauchst.>
Das reicht aber nicht. z.B. der Stack ist so ein Problem in C.
@Nathan
Hör auf das was Karl Heinz dir sagt. Er hat zu 100% recht damit.
Und es dauert wirklich nicht lange so ein Buch durchzuarbeiten.
Ich kenne das von den Studenten aus meiner Uni, die gerade frisch C
lernen.
Ich bin dort schon seit 2 1/2 Jahren als Tutor aktiv und sehe was es für
Probleme bereitet, wenn man gewisse Grundlagen nicht kennt.
Es macht wirklich keinen Unterschied, ob man vorher schon Java oder C#
gelernt hat. Ich habe von den Leuten auch schon viele gehabt, die
gemeint haben, Zeiger, malloc, free, etc. das brauch ich alles nicht.
Nur leider kommen da dann die komischsten Konstrukte zustande, die
teilweise sogar laufen. Mit gezielten Eingaben stürzt das Programm dann
aber ab. Und sowas soll nun mal nicht sein.
Will man ein gutes und sicheres Programm, muss man sich damit
beschäftigen.
Man muss sich reinhängen und damit auseinandersetzten. Wenn man das
nicht machen möchte, darf man sich hinterher nicht beschweren, wenn es
Probleme gibt. Ist halt leider so.
Dynamische Speicherverwaltung und Schutz vor Speicherlecks ist nun
wirklich nicht schwer und lässt sich wunderbar aus einem C-Buch lernen.
Und soviel kostet so ein Buch auch nicht.
Der Link von oben -> http://openbook.galileocomputing.de/c_von_a_bis_z/
da kannst du das ganze auch online durchlesen. Kenne nur die Java
Variante von denen, aber ich habe gehört, dass die C Variante auch ganz
brauchbar ist.
Gefährlich? Gefährlich ist ein physischer Kampf gegen einen anderen
Menschen mit einem Messer. Deswegen macht das praktisch keiner. Wenn du
beim Programmieren einen falschen Speicherbereich adressierst, stürzt
der Computer ab. Das wars. Du startest neu und es geht von vorne los. Du
kannst mit keiner Programmiersprache die Hardware kaputtmachen. Deswegen
programmiert fast jeder.
Nathan Palke schrieb:> Du> kannst mit keiner Programmiersprache die Hardware kaputtmachen. Deswegen> programmiert fast jeder.
Falsch. Wir sind hier bei mikrocontroller.net. Mit falscher Software
kriegt man Embedded-Hardware problemlos kaputt.
Mike Mike schrieb:> Oliver schrieb:>> Abdul K. schrieb:>>> z.B. der Stack ist so ein Problem in C.>>>> Äh, weshalb ???>>>> Oliver>> Dicke Rekursionen
Bzw. einfach viele Aufrufe irgendwie verschachtelt. Wobei Strukturierung
und Modularisierung hier noch extra negativ reinhauen.
Typischer Fehler ist eine nichtendende Rekursion aufgrund
Programmierprobleme. Schlicht was vergessen oder Dead-lock Situation.
Manche Betriebsysteme prüfen z.B. regelmäßig die aktuelle Stackposition
und schlagen Alarm wenn ein Mindestwert zum sonstigen Heap
unterschritten wird.
Eine vollständige Lösung ist das aber nicht! Und die achsotolle
Informatik im Studium umgeht das Problem elegant durch Einsatz dicker
Rechner.
Abdul K. schrieb:> Und die achsotolle> Informatik im Studium umgeht das Problem elegant durch Einsatz dicker> Rechner.
Dafür gibt es eine Vorlesung "Systemnahe Informatik".
Blöd nur, dass es danach immer noch keiner verstanden hat :(
Ich hab selber schon oft in anderen Vorlesungen gehört:
"Aber das war früher mal so, heute haben wir genug Speicher, da kümmert
sich keiner mehr drum".
Und dann sollen die nen kleinen µC programmieren -.-
Abdul K. schrieb:> Bzw. einfach viele Aufrufe irgendwie verschachtelt.
Das alles hat aber nichts mit Memory leaks o.ä zu tun, uns ist auch kein
Problem der Sprache C.
Und ja, mit Rekursionen kann man sich ins Knie schiessen, aber das in
vielen Progtammiersprachen, nicht nur in C. Der Vergleich mit der Schere
für 3 Jährige kam ja weiter oben schon.
C ist halt Programmieren ohne Netz und doppelten Boden, mit allen Vor-
und Nachteilen.
Oliver
Oliver schrieb:> Abdul K. schrieb:>> Bzw. einfach viele Aufrufe irgendwie verschachtelt.>> Das alles hat aber nichts mit Memory leaks o.ä zu tun, uns ist auch kein> Problem der Sprache C.>
1. ging es um Speicherüberlauf und
2. Ist es sehr wohl ein Problem von C, auch wenn es in vielen anderen
Sprachen ebenso vorhanden ist.
Und nach meinen bescheidenen Kenntnissen gibt es auch in der Theorie
keine Lösung für dieses Problem. Vielleicht kann da jemand was genaueres
schreiben.
Wenigstens ist es bei Stacks so, daß sie genau kein Memory Leak
besitzen!
Ach mir fällt noch ein, daß manche Prozessoren Kontrollregister für die
Online-Überwachung des Stacks besitzen.
> Und ja, mit Rekursionen kann man sich ins Knie schiessen, aber das in> vielen Progtammiersprachen, nicht nur in C. Der Vergleich mit der Schere> für 3 Jährige kam ja weiter oben schon.>
Versteif dich nicht auf die Rekursion. Es reicht ein hinreichend
kompliziertes Programm völlig aus und hat wohlmögliche gar keine
Rekursion inne. Es darf dafür sogar völlig korrekt sein!
> C ist halt Programmieren ohne Netz und doppelten Boden, mit allen Vor-> und Nachteilen.>
Genau! Was der einen Sprache ihr Goto ist der anderen ihr Stack-Problem.
Naja, das so nebenbei.
Nathan Palke schrieb:> stürzt> der Computer ab.
Wenns mal so wäre. Bei einer Vielzahl an Fehlern in C,C++ stürzt dein
Programm nicht einfach ab, sondern macht irgendetwas unvorhersehbares
zufälliges ("Undefined Behaviour") - was auch physisch gefährlich
werden kann, wenn das Programm Motoren oder Roboter steuert! Wenn
derartige Fehler in Browsern,Mailclients,PDF-Readern,JVM's,Flash-Playern
etc... sind und diese dadurch gegen Viren anfällig werden, die dann
deine Hausaufgaben von deinem PC löschen oder deine Homebanking-Daten
mitschreiben, würde ich das auch nicht mehr als völlig ungefährlich
hinstellen.
In C,C++ kann man schwer automatisch auf derartige Fehler prüfen, die
kann man nur durch saubere Programmierung vermeiden und mit viel
Erfahrung finden. Kleines Beispiel um auf den Geschmack zu kommen:
1
voidforwardMessages(){
2
charmsgBuffer[10];
3
intbyte;
4
intp=0;
5
while((byte=getc())!='\n')msgBuffer[p++]=byte;
6
sendBuffer(msgBuffer,p);
7
}
Wenn du den Fehler nicht findest und weißt was bei dessen Auftreten
passiert, hast du noch zu lernen...
Abdul K. schrieb:> Ach mir fällt noch ein, daß manche Prozessoren Kontrollregister für die> Online-Überwachung des Stacks besitzen.
Nicht nur manche, aber AVR dann doch nicht ;-)
Abdul K. schrieb:> Und nach meinen bescheidenen Kenntnissen gibt es auch in der Theorie> keine Lösung für dieses Problem.
Virtueller Speicher, Paging, Speicherschutz. Hilft natürlich nicht gegen
unendliche Rekursion, aber solche Programme lassen sich eben
prinzipbedingt nicht auf realen Rechnern ausführen.
Hans schrieb:> void forwardMessages () {> char msgBuffer [10];> int byte;> int p = 0;> while ((byte = getc ()) != '\n') msgBuffer [p++] = byte;> sendBuffer (msgBuffer, p);> }
Wurden aufgrund solcher Fehler nicht schon sehr viele Geräte gehackt?
Hab das immer nur mal am Rande mitbekommen, aber damit sollen doch
Hacker Rücksprungadressen oder was weiß ich was überschrieben haben.
Weiß da jemand was dazu?
Mike Mike schrieb:> Wurden aufgrund solcher Fehler nicht schon sehr viele Geräte gehackt?> Hab das immer nur mal am Rande mitbekommen, aber damit sollen doch> Hacker Rücksprungadressen oder was weiß ich was überschrieben haben.> Weiß da jemand was dazu?
Ja, das ist ein klassischer Buffer Overflow der zu solchen Zwecken
missbraucht werden kann. Das sind aber noch die trivialen Fälle.
Man kann auch Sachen konstruieren, die auch eingefleischte Profis ins
Schwitzen bringen können :)
Abdul K. schrieb:> Manche Betriebsysteme prüfen z.B. regelmäßig die aktuelle Stackposition> und schlagen Alarm wenn ein Mindestwert zum sonstigen Heap> unterschritten wird.> Eine vollständige Lösung ist das aber nicht! Und die achsotolle> Informatik im Studium umgeht das Problem elegant durch Einsatz dicker> Rechner.
Continuation-passing-style-Transformation -> nur noch endrekursive
Funktionen -> Tail-call elimination
Für den "Rest" gibt's Komplexitätstheorie.
D. I. schrieb:> Ja, das ist ein klassischer Buffer Overflow der zu solchen Zwecken> missbraucht werden kann. Das sind aber noch die trivialen Fälle.
In der Tat, aber dieser Fall passte in 7 Zeilen. Da kann man noch viel
mehr Spaß mit haben...
Mike Mike schrieb:> aber damit sollen doch> Hacker Rücksprungadressen oder was weiß ich was überschrieben haben.
Dazu musste noch nicht einmal Hacker sein, es braucht bloß eine Eingabe
eines Benutzers zu sein der nicht um die Einschränkungen dieses
Programms weiß, und schwupp hast du das Problem.
Jürgen Eder schrieb:> Warum eigentlich nicht C# auf dem Raspberry mal ausprobieren...?
Gründe:
- C wird nachgesagt, daß es maschinennäher sei als c# und damit
potentiell stabiler
- Ich möchte etwas für Pulseaudio programmieren und die Pulseaudio API
ist für C
- Ich möchte später am PC DirectX-Proxy-Dlls erstellen. Tutorials dafür
sind stets in C++.
- Ich möchte etwas Neues lernen, das Erfolgsgefühl erneut haben.