Hallo zusammen,
ich habe mal wieder ein kleines Problem undzwar mit Arrays.
Ich will eine Klasse schreiben, die ein Array besitzt. Die Größe dieses
Arrays soll aber abhängig von der initialisierung der Klasse sein. Ich
hatte mir das ganze so vorgestellt:
1
class t{
2
public:
3
int i[];
4
5
t(int j){
6
i[j];
7
}
8
}
aber so funktioniert das leider nicht. Kennt wer ne alternative wie ich
das hinbekommen könnte?
viele grüße blue
Arrays müssen immer statisch initialisiert werden, d.h. die Größe muss
zur Übersetzungszeit bekannt sein. Um zur Laufzeit Speicher anzufordern
musst du malloc() verwenden.
dito schrieb:> Arrays müssen immer statisch initialisiert werden, d.h. die Größe muss> zur Übersetzungszeit bekannt sein. Um zur Laufzeit Speicher anzufordern> musst du malloc() verwenden.
@blue
Lass malloc mal links liegen. In C++ macht man das anders.
Schau dir in deinem C++ Buch den Abschnitt über die STL an, und da
wiederrum über std::vector
Wenn du einen neueren Compiler hast, kannst du auch mal nachsehen, ob er
std::tr1::array unterstützt.
Du könntest ein dynamisches Array, einen std::vector, oder Templates
verwenden.
Dynamisch zb so:
class T {
public:
int * arr;
int size;
T(int s) size(s) {
arr = new int[s]; //malloc() geht auch c++ sieht aber new
vor
}
~T() { //destruktor notwendig damit kein memory leak entsteht
delete [] arr;
}
};
Persönlich würde ich (wenn es nicht Speicherkritisch oder
Performancekritisch zugeht) einen std::vector (oder std::list)
verwenden, allein wegen des Komforts...
Lukas
... und einen op= und einen Copy Constructor.
Und genau wegen all diesen Dingen, die man noch braucht um ein Klasse
bei Verwendung von dynamischer Allokierung sicher zu machen, ist es viel
einfacher diese Allokierung einem Spezialobjekt zu überlassen, zb.
std::vector
Dann braucht man weder Dtor, noch op=, noch CCtor.
Und fehlerfrei im Falle, dass die erste Schätzung der Anzahl der
Elemente zu klein war, ist es als Zugabe auch noch.
Und Performance ist kein Thema.
Wenn man std::vector halbwegs intelligent einsetzt, hat man keine
Performance Einbusen im Vergleich zu einem selbst angelegtem Array.
Danke für die schnellen Antworten.
Ich hatte aber vergessen zu sagen, dass das ganze für avr gedacht ist.
Da gibt es leider keine STL. Werd aber mal Lukas Vorschlag probieren.
Danke nochmals.
viele Grüße blue
blue schrieb:> Danke für die schnellen Antworten.>> Ich hatte aber vergessen zu sagen, dass das ganze für avr gedacht ist.
Welchen?
> Da gibt es leider keine STL. Werd aber mal Lukas Vorschlag probieren.
Auf einem µC mit arg begrenztem Speicher willst du dynamische
Speicherallokierung vermeiden, wie der Teufel das Weihwasser.
Was machst du, wenn der Speicher zur Neige geht?
Du kannst nicht einfach "Out of Memory" hinschreiben und zum
Betriebssystem zurückkehren!
a) hast du kein Betriebssystem
b) Steuerungen müssen unter allen Umständen weiterlaufen.
So etwas wie einen "Out of Memory" darf es nicht geben!
blue schrieb:> Ich hatte aber vergessen zu sagen, dass das ganze für avr gedacht ist.
Ob man da aber mit copy-ctor, operator= etc. spielen will, sei mal
dahingestellt.
Wenn man weiß, was man macht, ist es i. Ordnung.
Aber im Allgemeinen sind die Warnungen nicht von der Hand
zu weisen:
Karl heinz Buchegger schrieb:> .. und einen op= und einen Copy Constructor.>> Und genau wegen all diesen Dingen, die man noch braucht um ein Klasse> bei Verwendung von dynamischer Allokierung sicher zu machen,...
Ich nutze einen Roboter mit einem AT90CAN128.
Das Ganze wird als Tupel für ein DBMS gebraucht. Und für spezielle
Funktionen brauch ich eine klare Struktur meiner Daten. Und da
gespeicherte Tupel unterschiedlich viele Attribute haben können, muss
ich die Größe des Arrays meinem Datensatz anpassen. Ohne Array wird das
ganze (inkl. der zu Programmierenden Funktion) um einiges Komplizierter.
Die Menge der Tupel im Hauptspeicher soll ja garnicht so groß werden und
die Tupel (also auch das Array) werden später wieder frei.
Betriebssystem: soll garkeins haben, um Speicher zu sparen.
viele Grüße blue
blue schrieb:> die Tupel (also auch das Array) werden später wieder frei.
Aber auch dann kann es passieren, daß der Speicher zwar frei
ist, aber irgendwann zu fragmentiert, um etwas neues anlegen zu
können.
Mit etwas Verstand könnte man sich notfalls eine eigene
Speicherverwaltung überlegen.
Die Fehlerbehandlung wird auf jeden Fall spannend.
blue schrieb:> Ich nutze einen Roboter mit einem AT90CAN128.
d.h 4KB SRAM
> Und da> gespeicherte Tupel unterschiedlich viele Attribute haben können,
gibt es eine Obergrenze?
Wenn es eine gibt, dann nutze sie.
Lege alles statisch für diese Obergrenze aus.
> muss> ich die Größe des Arrays meinem Datensatz anpassen. Ohne Array wird das> ganze (inkl. der zu Programmierenden Funktion) um einiges Komplizierter.> Die Menge der Tupel im Hauptspeicher soll ja garnicht so groß werden und> die Tupel (also auch das Array) werden später wieder frei.
Dir ist klar, dass das einfache Zusammenzählen der Speicherallokierungen
für den Komplettverbrauch eine Milchmädchenrechnung ist, die ganz
schnell nach hinten losgehen kann? Stichwort: Speicherfragmentierung
Du kannst zb
4K frei haben
1K allokieren
2K allokieren
1K allokieren
jetzt gibst du die beiden 1K Blöcke wieder frei. Nach Adam Riese sind 2K
allokiert und 2K frei. Und trotzdem gibt dir malloc einen NULL Pointer
wenn du 1.5K anforderst.
Warum?
Weil zwar 2k frei sind, das stimmt schon, aber nicht in einem Stück! Die
2K liegen in Form von 2 jeweils 1K großen Blöcken vor. In keinen von
beiden passen aber deine 1.5K hinein.
(Zahlen jetzt frei erfunden um das Problem zu zeigen. Du wirst kleinere
Zahlen haben. Dafür hast du aber auch mehr im Speicher und nicht die
ganzen 4K für dich alleine)
Karl heinz Buchegger schrieb:> Und trotzdem gibt dir malloc einen NULL POinter> wenn du 1.5K anforderst.
Selbst bei 1K bekommt er einen null Pointer, da die Speicherverwaltung
schon den Rest gefressen hat.
@ TE: Was genau meinst Du mit
Tupel für ein DBMS gebraucht. DBMS ist für mich database management
System. Und ein Tpel eine Menge von (n) Elementen/Werten.
Lukas schrieb:> Wenn das dem Problem nicht entgegensteht würde ich einfach verkettete> Listen nehmen, oder spricht da was dagegen?
mehr Speicheroverhead.
Gefahr für Fragmentierung größer
Vorteile:
mehrere kleinere Speicheranforderungen anstatt einer großen.
Dadurch ist die Gefahr einer Fragmentierung zum Opfer zu fallen
geringer.
Ein grundätzlicher Nachteil dynamischer ALlokierung auf einem AVR mit
wenig Speicher (und 4K sind wenig) wurde noch gar nicht angesprochen.
Bei rein statischer Allokierung muss man ein Auge darauf haben, dass
einem der Stack nicht in die Daten hineinwächst.
Kommt dynamische Allokierung mit ins Spiel gilt dann auch die Umkehrung:
Man muss ein Auge darauf haben, dass einem der Heap nicht in den Stack
hineinwächst, wachsende Daten also nicht den Stack korrupten.
Wenn man von malloc eine NULL bekommt, ist es schon längst zu spät. Dann
hat man schon längst den Stack niedergebügelt.
Alles in allem gute Gründe, möglichst alles statisch festzunageln und
auf Obergrenzen zu dimensionieren, selbst wenn dann in Einzelfällen
Speicher nicht benutzt wird. Aber so hat man dann wenigstens fixe
Kennzahlen: Bis hierher und nicht weiter.
Also ich hab mich oben falsch ausgedrückt,
das Ganze ist wie gesagt für ein DBMS. Unterschiedliche Anwendungen
dieses DBMS haben je nach verwendetem Systemkonfiguarationen wenige
verschiedene Tupelarten mit unterschiedlichen Längen. Die dann aber sich
nicht ständig Ändern. Also feste Größen pro Datenbank, die sich aber von
Anwendung zu Anwendung ändern.
Dank euch werde ich als Empfehlung für die Anwendungsprogrammierung klar
herausstellen, das immer nur eine feste Anzahl an Tupeln deklariert
werden sollte, die dann nicht!! freigegeben werden, sondern immer wieder
mit neuen Werten bestückt werden. Vielleicht mach ich das auch über eine
Schnittstelle, die dann die Tupel verwaltet/ initialisiert. (Achtung
keine Speicherverwaltung)
Die Möglichkeit mit einer festen Obergrenze ist leider nicht so
praktikabel, da sich diese von Anwendung zu Anwendung ändert und
eigendlich nicht im Code des DBMS geändert werden soll.
Danke für eure Hilfe, damit habt ihr mich auch auf die potentielle
Fehlerquelle Tupel hingewiesen. (an anderer Stelle habe ich genau das
Problem erst behoben und hier vergesse ichs ;-))
viele grüße blue