die frage steht ja eh schon im betreff! kann mir da jemand die syntax sagen plz? mfg florian
btw: Falls meinst einen cast zu brauchen, ist malloc fehl am Platze. In diesem Fall brauchst du new, da du C++ programmierst. Ein Cast ist z.B. dieses "(char*)" vor malloc: char* p = (char*)malloc(0); Der Cast ist hierbei völlig unnötig und sollte weggelassen werden. Wenn der Compiler dann meckert, brauchst du kein malloc.
mein compiler (ICCAVR) sagt mir, dass ich mit malloc speicherplatz reservieren kann! die syntax sieht in der hilfe so aus: void *malloc(size_t size); is ja alles schön und gut - nur wie weiß ich jetzt, wo sich mein frisch reservierter speicherplatz befindet? mfg florian
malloc gibt einen Zeiger auf den reservierten Speicher zurück. (Warum hab ich nur grad das ungute Gefühl die Doku zu rezitieren?) Zeiger sind in wirklich absolute C Grundlagen, die man kennen sollte. Bevor du versuchst, Mikrocontroller mit C zu programmieren, solltest du C richtig lernen. Das geht am einfachsten mit simplen Konsolenanwendungen, etwa unter Windows oder Linux.
simple grundlagen hin oder her :-) ich besuche zZ die 5. Klasse der Höheren Technischen Lehranstalt in Innsbruck mit Fachrichtung Elektronik-Technische Informatik! da ich aber bis jetzt meine schönen, unschuldigen Controller der Atmelserie nur mit Assembler programmiert habe, tu ich mich da ein wenig schwer! ich versuche jetzt, wie ich es von Assembler gewohnt bin, eine Tabelle anzulegen AVRStudio-Quellcode: sepp: .byte 5 so habe ich 5 byte reserviert mit der Adresse sepp, die darf niemand anderer haben dassselbe versuche ich jetzt in C ich habe einen Zeiger *sepp auf das erste Element der Liste/Tabelle; wenn ich jetzt aber einfach irgendeinen Wert nach *(sepp+1) schreibe, dann kann ich Glück haben oder ich überschreib mir andere Werte... also eine reformulierte Frage: wie kann ich unter C Speicherplatz reservieren? Entschuldigung und Danke im voraus mfg florian
Entweder dynamisch mit malloc oder statisch mit Variablendefinitionen. Bei fünf Bytes ist letzteres häufig sinnvoller. uint8_t sepp[5]; sepp zeigt nun auf das erste von 5 Bytes.
Kleines Beispiel: struct sMeineDaten { int a; int b; char c; }; void main(void) { struct sMeineDaten *Data; Data = malloc(sizeof(struct sMeineDaten)); Data->a = 5; ... ... ... free(Data); } Hilft das?
da ICCAVR keinerlei Simulation zulässt, kann ich quasi nur raten, ob char* p = (char*)malloc(5); funktioniert. dh jetzt also, der zeiger p zeigt auf die erste Stelle der 5 reservierten Speicherplätze mit jeweils 8Bit - 1Byte? @Tom: bei deinem bsp wäre es wohl sinnvoller new zu nehmen? danke schon mal mfg Florian
malloc gibt immer einen Pointer zurück. Sollte keine Speicher mehr vorhanden sein ist p NULL ( Nullpointer ). Das kannst Du abfragen. if( !p ) { // sch... kein Speicher } else { // Super, kann noch arbeiten *++p = 1; // erste Stelle *p = 2; // zweite Stelle *p++; // dritte *p = 3; }
> da ICCAVR keinerlei Simulation zulässt, kann ich quasi nur raten, ob > char* p = (char*)malloc(5); > funktioniert. Arghh, ich habe doch sogar zwei Mal geschrieben, dass man es so nicht machen soll! Bitte lass diesen Cast vor malloc weg, so wie Tom es gezeigt hat. new kann man nur benutzen, wenn man C++ programmiert. Wenn der Compiler sich über einen fehlenden Cast vor malloc aufregt, ist es ein C++-Compiler. Nur in diesem Fall wäre new angebracht. In Toms C-Code würde new gar nicht funktionieren. Wenn du fünf Bytes reservieren willst, würde ich das aber nicht dynamisch machen, außer du baust eine verkettete Liste oder ähnliches. char sepp[5]; Das reserviert genau fünf Bytes Speicher.
1. meide malloc 2. meide malloc! 3. meide malloc! new muss in der stl implementiert sein, um es nutzen zu können, eine stl ist bei den meisten Compilern allerdings (IIRC) kaum vorhanden...
moin, nur mal zum klarstellen. wenn du in einer funktion 5 byte speicher brauchst kannst du diese am einfachsten mit char sepp[5]; reservieren. sepp zeigt nun auf das 1. byte, sepp+1 auf das 2. usw. reinschreiben kannst du dann mir *(sepp+n) = j; oder mit sepp[n] = j; dabei kannst du sicher sein, dass wenn n nicht größer als 4 und nicht kleiner als 0 ist, du immer ein byte des reservierten speicher ansprichst. wenn du das innerhalb einer funktion machst, steht dieser im gültigkeitsbereich der funktion dauerhaft zur verfügung. verlässt du die funktion, gilt der speicher nicht mehr als reserviert und kann von anderen funktionen überschrieben werden. soll der speicher während der gesammten laufzeit des programms reserviert bleiben, muß er entweder in der funktion main() reserviert werden und der zeiger darauf an die aufzurufenden funtionen übergeben werden, oder du legtst im global an. wenn die größe des benötigten speicher erst zur laufzeit bestimmt werden kann, benutzt du malloc(); char* sepp = malloc( i * sizeof(char) ); wobei i = menge der zu reservierenden bytes ist. sepp zeigt nun sicher auf das 1. element des reservierten speicher. zugriff ist nun wieder durch dereferenzierung möglich: *(sepp+n) = j; wobei n werte von 0 bis i-1 annehmen darf. dieser speicher bleibt solange reserviert bis du ihn mit free(sepp); wieder frei gibst.
@Steffen Solltest noch der Vollständigkeit halber erwähnen, daß es eine schlechte Idee ist den Zeiger von malloc wegzuwerfen oder zu verändern, ohne vorher eine Kopie anzulegen. Spätestens beim free rächt es sich bitter :-) @Chris Wenn der Compiler mault kann aber auch der Prototyp (stdlib.h) fehlen, der Rückgabetyp defaultet auf int, int passt nicht auf char*, Warning.
Hallo... Habe mir die verschiedenste Beitraege durchgelesen und habe mich auch entschieden mal etwas zu schreiben: - verwende malloc, wenn Du dynamischen Speicher brauchst. char* p = malloc (xxxBytes); Dieser Speicher wird auf dem Heap angelegt. - Wenn Du allerdings nur ein paar Bytes brauchst, mach Dir ein Array. char aP [XXXBytes]; Dieser Speicher wird auf dem Stack angelegt. Bevor Du p mit Null beschreiben wills, muss Du den Speicher mit "free" freigeben, sonst ist Dein Speicher im Heap noch als "belegt" markiert und Du kommst nicht wieder an den Speicher dran. Alex
@OldBug: new ist AFAIK kein Bestandteil der STL. new ist ein Sprachfeature von C++. Nur die globale Funktion "operator new" muss von der standard-lib bereitgestellt werden (libsup++ sollte das machen IIRC). Beim avr-g++ ist das noch nicht der Fall, aber man kann sich ganz einfach helfen: void* operator new(unsigned int size) { return malloc(size); } void operator delete(void* p) { free(p); } Diese Zeilen in eine Quellcodedatei einfügen, schon funktionieren new und delete wie gewünscht. @Zotteljedi: Stimmt, hatte ich nicht bedacht. Ich programmiere einfach zu selten C, ich bin eher C++-Programmierer.
Das ist natürlich der einfachste Weg. Allerdings befürchte ich, daß das in einer Fragmentierungsschlacht endet, weshalb man ja auch bei C malloc meiden sollte... Aushilfe würde hier ein "schlaues" Memorymanagement schaffen, aber das nur am Rande. Jörg Wunsch hat zwar auch schon etwas für malloc/free getan, aber das wird wohl für das exzessive Nutzen von new und delete bei weitem nicht ausreichen.
Jetzt bin ich aber gespannt, wie verhindert C++ (Du scheinst damit "jedes C++, by Design, immer und überall" zu meinen) denn das Verwenden von vielen, unterschiedlich großen Speicherbereichen, wenn viele, unterschiedlich große Speicherbereiche angefordert werden? Fragmentierung gibt es IMHO immer, wenn Speicher allokiert und freigegeben wird, und das mehr als einmal und parallel. Man kann schlechte Algorithmen für Memory Allocator sowohl für C als auch für C++ schreiben. Gute ebenso.
Wieso denn bitte jedes? Ich spreche hier ausschliesslich von avr-gcc/avr-g++, bei dem die C++ implementation nun mal nicht sonderlich verfolgt wird. Und da malloc/free nicht für häufigen Einsatz implementiert sind (es hat sich inzwischen schon einiges getan, nachdem Jörg realloc implementiert hat), sollte man dann beim verwenden von malloc/free für new und delete auch Sparsam sein! Schau Dir die implementierung von malloc und free doch einfach mal an...
@Zotteljedi: Nein, du hast mich falsch verstanden. Der Operator new ist ein Sprachfeature von C++ und damit bei jedem C++-Compiler gleich definiert. Der Operator new hat zwei Aufgaben zu erfüllen: Speicher beschaffen und ihn zu initialisieren. Ersteres erledigt der Operator new, indem er die Funktion "operator new" aufruft. Diese Funktion muss von der standard-lib bereitgestellt werden. Den zweiten Schritt, das Initialisieren, schafft der Operator new wieder ohne fremde Hilfe. Er ruft einfach den passenden Konstruktor auf. Beim avr-g++ mangelt es nur an der Funktion "operator new", nicht am Operator new selbst.
Ich halte malloc() auf MCs für absolut witzlos. Man kann auf einem AVR keine Programme nachladen. D.h. der maximale Speicherbedarf ist also schon zur Compilezeit berechenbar und muß in jedem Fall sichergestellt werden !!! Was nützt es, wenn malloc() fehlschlägt ? Auf dem PC kannst Du dann eine Ausschrift machen "Bitte schließen Sie eine Anwendung" aber z.B. nicht auf Deiner Waschmaschine. Daher ist malloc() nur Rechenzeit-, Code- und SRAM-Verschwendung (unnützer Verwaltungsaufwand). Und da der AVR keine MMU hat, kann man auch eine Fragmetierung nicht vermeiden. Ich will z.B. eine Heizungssteuerung nicht jeden Monat resetten müssen, nur weil der Speicher fragmentiert ist. MC-Anwendungen sollen ja, anders als PCs, auch mal 10 Jahre am Stück ohne Reset durchlaufen können. Daher senkt malloc() auch drastisch die Zuverlässigkeit. Peter
@Chris: nur weil new genau beschrieben ist (wie es aussieht, sich anfühlt), muß es noch lange nicht von jedem Compiler gleich implementiert werden! Wirf doch mal einen Blick in den Standard, da steht von Interna genau gar nichts drin. Das ist auch gut so. Intern läuft da so ziemlich die gleiche Mechanik wie bei malloc/free an, heißt nur anders. Das Problem "Speicher beschaffen" ist immer das gleiche, egal wie Du es verkleidest.
@Oldbug: Dann habe ich Dich falsch verstanden. Du meintest also damit, daß man bei C malloc meiden soll auch, daß man bei C++ new meiden soll. Dann sind wir ja wieder im Reinen. @Chris: Hab Dich verwechselt, natürlich weißt Du, wie new intern arbeitet. War etwas vorschnell gepostet.
@Peter : Für Waschmaschinen und Heizungen mag das angehen. Für etwas "höhere" Anwendungen gilt die Überflüssigkeit von malloc() und free() auf keinen Fall ! Ich entwickle hier (Diplomarbeit) an einem Betriebssystem mit und da benötigt man sehr wohl solche Funktionalitäten, da zum einen zum Compile-Zeitpunkt nicht klar ist, wie große Datenobjekte verarbeitet werden und zum anderen ist auch das Code-Nachladbarkeitsargument im Kontext mit Betriebssystemen haltlos. Beispiel : Auf meiner Anwendung hier kann zur Laufzeit ein Monitor-Feature aktiviert werden. Natürlcih ist dieses als Programmcode vorhanden, belegt aber außer ROM keine Resourcen. Wird es gestartet, muss es Stack und RAM-Speicher für Puffer bekommen. Außerdem können mit dem Betriebssystem hier Tasks verlagert werden und deren Speicherbedarf ist ebenfalls nicht zur Compilezeit bekannt. Sicher kann man alle Probleme immer auch ohne malloc() und free() lösen - aber warum ? Schließlich verwenden wir auch Hochsprachen und Compiler, wo man auch mit binärcode alle Probleme lösen kann. Für alle : malloc() und free() sind nicht im Allgemeinen schlecht. Man muss sich die spezifische Implementierung anschauen. Ich habe hier selbst einen malloc()/free() Algorithmus mit best-fit-Strategie und Freispeicherzusammenfassung implementiert. Fragmentierung ist hier schon ein sehr viel kleinere Problem. Man muss eben auf µControllern auch immer Zugeständnisse an solche Funktionen machen, da man eben nicht beliebig viel Speicher und Rechenzeit für die Verwaltung ausgeben möchte. MfG, Khani
@Khani, "Sicher kann man alle Probleme immer auch ohne malloc() und free() lösen - aber warum ?" Ich muß hochzuverlässige Anwendungen programmieren und da kann ich es mir nicht leisten, daß malloc() den Speicher fragmentieren könnte oder ein false zurückliefert. Es muß immer genügend Speicher für alle denkbaren Konstellationen zur Verfügung stehen. Und das geht nunmal am sichersten, wenn jede Task immer den maximal nötigen Speicher alloziiert. Und am Ende der Programmentwicklung werden dann alle Speichergrößen der maximal gleichzeitig aktiven Tasks addiert und geprüft, ob dieser RAM auch verfügbar ist. Da auch grundsätzlich keine rekursiven Funktionen zugelassen werden, ist das relativ einfach und vor allem genau. Peter
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.