www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik wie verwende ich *malloc();??


Autor: ubootfanat (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
die frage steht ja eh schon im betreff!

kann mir da jemand die syntax sagen plz?

mfg florian

Autor: Blubb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
für sowas gibts googel

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und die hilfe datei des c-compilers deiner wahl

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: ubootfanat (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: ubootfanat (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: ubootfanat (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Steffen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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;
     }

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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.

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: tenner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Zotteljedi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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.

Autor: Alex1 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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.

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Zotteljedi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: OldBug (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Zotteljedi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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.

Autor: Zotteljedi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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.

Autor: Khani (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.