Hi Ich würde für ein embedded projekt ganz gerne c++ einsetzen. Allerdings will ich auf dynamische speicherverwaltung verzichten. sprich container basierend auf einem statischen array der Templatevariablen. und vor allem würde ich gerne einen Teil der strign funktionalität nutzen. Allerdings dürfte beim Konstruieren eines Stringobjektes nichts dynamisch alloziert oder kopiert werden, sondern der string sollte als puffer direkt den übergebenen char Puffer benutzen. HAt jemand schon mal sowas gemacht? gibt es eine (freie) Abwandlung der STL speziell für solche embedded anforderungen? Klar, das ist alles kein Hexenwerk, aber warum das Rad zwei mal erfinden. Gruß Vlad
schau dir mal placement-new an, vielleicht hilft dir das ein bisschen weiter.
achso und schau dir an, wie man mittels Templates fixe Größen übergeben kann. Also sowas wie MeinString<30> meinString; wäre möglich, und mit dem Wert 30 setzt du im Template dann ein statisches Array. template<size_t max> class xy { ... unsigned char[max] array; ... }; Ich weiß, ist wieder zum Selberbauen, fertige Lösung weiß ich leider nicht.
Der Aufwand das mit der STL hinzubekommen steht in keinem Vergleich zu den wenigen Vorteilen die man dadurch gewinnt. Die STL ist schon von ihrer Architektur ziemlich ungeeignet für Embedded-Software in kleinen Mikrocontrollern. C++ selber ist in der Umgebung auch nicht das Wahre, und degeneriert schlussendlich meist zu C mit ein bisschen Dekoration. Da kann man auch direkt C nehmen, wenn man auf die wirklich interessanten C++-Eigenschaften verzichten muss. Um es anders auszudrücken, ich bin immer wieder erstaunt, wie viel Aufwand Leute betreiben wollen um etwas nicht zu lernen. In diesem Fall ein paar Strings von Hand in C (nicht C++) mit Pointern zu handhaben. Der Schlüssel die Speicherverwaltung von string zu ändern ist auch nicht Placement-new alleine, sondern auch ein allocator. Zumindest theoretisch. In der Praxis wird das Allocator-Argument gerne ignoriert. Dann steht man richtig blöd da.
vfcfsdfs schrieb: > schau dir mal placement-new an, vielleicht hilft dir das ein bisschen > weiter. das hilft an der Stelle ja nicht. das Placement new legt ja nur die Struktur in den vorbereiteten Speicher. String funktioniert ja eher so:
1 | class String |
2 | {
|
3 | public:
|
4 | String(const char* input) |
5 | {
|
6 | size = strlen(input); |
7 | capacity = size+1; |
8 | buffer = new char[capacity]; |
9 | strcpy(buffer, input) |
10 | }
|
11 | ~String(){ |
12 | delete[] buffer; |
13 | }
|
14 | |
15 | private:
|
16 | int size; |
17 | int capacity; |
18 | char* buffer; |
19 | }
|
Mach ich ketzt ein placement new:
1 | static String strBuffers[10]; |
2 | String* s = new(&strBuffers[5]) String(charbuffer); |
wird der String zwar in den Statischen Puffer construiert (also dessen Members size, capacity und der buffer-Pointer), aber der eigentliche Zeichenkettenpuffer ist nachwievor dynamisch per new allozierter Speicher. Der String würde sowieso auf dem Stack landen. es gibt ja dann noch die allocatoren, den man dem String als template paraemter übergeben kann. aber so ganz das, was ich will ist das auch nicht. Eigentlich bräuchte man eine Wrapper-Klasse, die weitestgehend kompatibel zu std::String ist, aber nur auf dem übergebenen Puffer arbeitet, also keine Operationen ausführt, die die maximale länge überschreiten. Das Gleiche bei den containern. vfcfsdfs schrieb: > achso und schau dir an, wie man mittels Templates fixe Größen übergeben > kann. das möchte ich ja auch nicht. Dann habe ich ja für jede Pufferlänge den Template-Code instanziiert. Die Länge selbst kann schon ein Laufzeitparameter sein. Das man das selbst schreiben kann ist keine Frage, aber das STL-Kompatibel hinzubekommen ist schon eine ziemliche Herausfoderung (zb richtige Funktionsweise der Iteratoren, damit auch STL-Hilfsfunktionen funktionieren)
Ist so schrieb: > C++ selber ist in der Umgebung auch nicht das Wahre, > und degeneriert schlussendlich meist zu C mit ein bisschen Dekoration. Alleine schon wegen diesem bisschen Dekoration lohnt sich die Verwendung von C++ > Da kann man auch direkt C nehmen, wenn man auf die wirklich > interessanten C++-Eigenschaften verzichten muss. Aber lieber ein bisschen davon, als in Plain-C umständlich die Konzepte, die man problemlos nutzen könnte, nachzuprogrammieren. Und genau hier, weiß ich wovon ich rede - das kannst du mir glauben. > > Um es anders auszudrücken, ich bin immer wieder erstaunt, wie viel > Aufwand Leute betreiben wollen um etwas nicht zu lernen. In diesem Fall > ein paar Strings von Hand in C (nicht C++) mit Pointern zu handhaben. Da du micht nicht kenntst, maßt du dir hier ganz schön was an. > > Der Schlüssel die Speicherverwaltung von string zu ändern ist auch nicht > Placement-new alleine, wie ich schon (scheinbar zeitgleich mit dir) schrieb, ist das placement new in dem Fall überhaupt keine Hilfe. > sondern auch ein allocator. Zumindest > theoretisch. In der Praxis wird das Allocator-Argument gerne ignoriert. > Dann steht man richtig blöd da. Das Allocator element war mir bisher leider auch noch nie eine Hilfe. Die Bedingung der Austauschbarkeit verschiedner Allocator Instanzen hat bisher immer gestört
Hey Vlad, ich würde am ehesten den Ansatz mit eigenem Allocator versuchen. Mit maps und vektors habe ich das schon gemacht um diese im shared memory ablegen zu können. Wie sich das bei std::string verhält weiss ich nicht, ist aber zu untersuchen. Wenn ich morgen an meiner Kiste bin werde ich mir das mal ansehen, ist es doch ein knackiges Problem. Grüsse, René
Mit allocator wird das nicht funktionieren, da der Anwendungszweck ein anderer ist. Ein Allokator versorgt alle Strings, die mit diesem Allokator als Templateparameter erzeugt wurden mit Speicher. Das heißt, wenn ich einen AllokatorX schreibe und zwei String<xhar, AllokatorX > s1; String<xhar, AllokatorX > s2; habe habe ich quasi trotdem nur einen Allokator, bzw, die instanzen der beiden Allokatoren, die in den Strings enthalten sind müssen austauschbar sein. Allokatoren sind also quasi Pseudo-Singeltons. Ich hab zwar mehrere Instanzen, aber egal welche instanz ich mir nehme, sie mus sich genauso verhalten, als hätte ich die andere benutzt. Das heißt man hat irgendwo einen großen Puffer, aus denen sich alle String<xhar, AllokatorX > dynmisch bedienen, wenn sich ihre größe ändert. Der allokator muss also da sich darum kümmern, dass er eine Fragmentierung minimiert. Was ich möchte ist ja quasi mur ein Wrapper um ein C-Array, was irgendwo statisch ist mit einer maximalen Größe. Also quasi eine std::string-Abart, der man im Konstruktur den Speicher und die Größe gibt und die dann ganz normal darauf arbeitet, nur eben nicht bei Bedarf neuen speicher anfordert.
Hmm.... Das verstehe ich nicht. Was hindert Dich daran zwei verschiedene Allokatoren zu nehmen? Der Interoperabilität tut sich deswegen nichts.
Und wenn Du eine eigene allocator Methode definierst ist auch mit reallocation nichts. Das heisst Du hast den allozierten Speicher im Griff.
Vlad Tepesch schrieb: > Ist so schrieb: >> C++ selber ist in der Umgebung auch nicht das Wahre, >> und degeneriert schlussendlich meist zu C mit ein bisschen Dekoration. > Alleine schon wegen diesem bisschen Dekoration lohnt sich die Verwendung > von C++ Aus praktischer Erfahrung kann ich dir sagen es lohnt nicht. Man landet bei so vielen Konventionen "benutz das nicht, benutze jenes nur so", die man dann konsequent einhalten muss, damit das was wird, dass es zum Schluss keinen Spaß mehr hat. Hinzu kommt, dass man sich die Maintenance-Probleme von morgen einbaut, da man morgen schon nicht mehr weiß, warum man welche Konventionen warum eingeführt hat. Aber Hauptsache, man hat seine Lieblingssprache mit dem Vorschlaghammer für etwas passend gemacht, für das sie nicht wirklich passt. > Und genau hier, weiß ich wovon ich rede - das kannst du mir glauben. Das glaube ich dir nicht. Dann müsstest du nicht nach einer String-Bibliothek fragen und dich nicht mit Typen wie mir abgeben. Dann hättest du dir mit all deiner Erfahrung still und heimlich, ruckzuck einfach was gebastelt, schließlich weißt du wovon du redest.
vfcfsdfs schrieb: > achso und schau dir an, wie man mittels Templates fixe Größen übergeben > kann. > Also sowas wie MeinString<30> meinString; wäre möglich, und mit dem Wert > 30 setzt du im Template dann ein statisches Array. Das ist aber etwas ungeschickt, weil jeder Wert für den template-Parameter einen neuen Typ erzeugt. D.h. MeinString<30>, MeinString<31>, MeinString<32> etc. sind jeweils eigene Datentypen; für jeden benutzten wird Code erzeugt. Möchte man einen Typ haben und trotzdem verschiedene Längen für die Objekte haben, ist es besser, die Länge im ctor anzugeben.
Rene H. schrieb: > Hmm.... Das verstehe ich nicht. Was hindert Dich daran zwei verschiedene > Allokatoren zu nehmen? Der Interoperabilität tut sich deswegen nichts. duplizierter Code, da für jeden Allokatortyp ein neuer string typ erzeugt wird, die zudem inkompatibel untereinander sind. Rene H. schrieb: > Und wenn Du eine eigene allocator Methode definierst ist auch mit > reallocation nichts. Das heisst Du hast den allozierten Speicher im > Griff. das schon, aber der String selbst fordert ja trotzdem munter Speicher in unterschiedlichsten Größen an und kopiert den im C'tor übergebenen String in diesen Puffer.
Ist so schrieb: > Aber Hauptsache, man hat seine Lieblingssprache mit dem Vorschlaghammer > für etwas passend gemacht, für das sie nicht wirklich passt. Das Argument hätte ich gelten lassen, wenn ich nach Visual Basic, Java oder C# gefragt hätte, aber so ist es einfach nur lächerlich. Ist so schrieb: > Aus praktischer Erfahrung kann ich dir sagen es lohnt nicht. Dann lehrte uns unsere Erfahrung unterschiedliche Sachen. Meine Erfahrung mit großen C-Projekten (mehrere 100 Files und mehrere 10.000 loc) hat mir gezeigt, dass das C++ häufig sehr zur Lesbarkeit des Codes beigetragen hätte. Alleine durch Namespaces und Memberfunktionen und Constanten/Enums im Class-Scope herrscht vielmehr Ordnung im globalen Namensraum. Allein deswegen lohnt es sich. Wenn man auf Features wie Polymorphie angewiesen ist, wird C sogar zum Graus, wenn eine Funktion auf einmal virtuell werden soll, passt man 100e Stellen Code an (ob automatisiert oder von Hand sei einmal dahingestellt), weil man die Funktion in die VTable packen muss und alle bisherigen normalen Funktionsaufrufe durch VTable-Funktionspointer-Calls ersetzen muss. > Man landet > bei so vielen Konventionen "benutz das nicht, benutze jenes nur so", die > man dann konsequent einhalten muss, damit das was wird, dass es zum > Schluss keinen Spaß mehr hat. was ist so schwer daran sich ein subset an c++ zu definieren, was man benutzen kann? Als grobe Regel: alles was dynamisch Speicher holt ist nicht erlaubt. RTTI ist nicht erlaubt. > da man morgen schon nicht mehr > weiß, warum man welche Konventionen warum eingeführt hat. Du weißt wofür es eine Dokumentation gibt? Ist so schrieb: >> Und genau hier, weiß ich wovon ich rede - das kannst du mir glauben. ups, hier ist das komma aber ganz schön verrutscht > Das glaube ich dir nicht. Dann müsstest du nicht nach einer > String-Bibliothek fragen und dich nicht mit Typen wie mir abgeben. Dann > hättest du dir mit all deiner Erfahrung still und heimlich, ruckzuck > einfach was gebastelt, schließlich weißt du wovon du redest. Natürlich kann man das selbst schreiben, aber erstens ging es mir nicht nur um eine String-Bibliothek, sondern eher eine Art embedded-STL, zweitens ist schon vorhanden und getestet immer besser als selbstgeschrieben, drittens: machst du das bei deinem Arbeitgeber auch so? "Ich hab nicht geschaut, ob das schonmal jemand gemacht hat. Ich bin so der C-Checker ich mach das lieber selbst komplett neu" Deshalb zitiere ich mein Eingangspost mal: Vlad Tepesch schrieb: > Klar, das ist alles kein Hexenwerk, aber warum das Rad zwei mal > erfinden. Außerdem, um diese Sinnlosdiskussion (@rene: das ist nicht an dich gerichtet) zu beenden: Die Frage war: Vlad Tepesch schrieb: > HAt jemand schon mal sowas gemacht? > gibt es eine (freie) Abwandlung der STL speziell für solche embedded > anforderungen? und nicht, "Ist eure Lieblingssprache C oder C++?" oder "Was denkt ihr von jemanden, der nicht alles selbst schreibt, sondern erst mal nach verfügbaren Lösungen schaut."
Ist so schrieb: > Vlad Tepesch schrieb: >> Ist so schrieb: >>> C++ selber ist in der Umgebung auch nicht das Wahre, >>> und degeneriert schlussendlich meist zu C mit ein bisschen Dekoration. >> Alleine schon wegen diesem bisschen Dekoration lohnt sich die Verwendung >> von C++ > > Aus praktischer Erfahrung kann ich dir sagen es lohnt nicht. Das kann man aber so nicht stehen lassen. Was sind 2 der Hauptprobleme in C * Arrays wissen nicht wie groß sie sind * Strings sind kein eigener Datentyp sondern beruhen auf einer Konvention Und gerade in diesen beiden Bereichen kann dir C++ schon enorm unter die Arme greifen, wenn es darum geht robusten Code zu produzieren. Eben genau deshalb, weil du die Möglichkeit hast, die Konventionen, bzw. was viel wichtiger ist, das Einhalten dieser Konventionen, in einer Klasse zu sammeln und so zu verpacken, dass ein Verwender der Klasse nicht mehr dagegen verstossen kann. Ersetze ich 5 einzuhaltende Konventionen durch lediglich 1 an die ich mich halten muss, dann habe ich dadurch etwas gewonnen. Ein Verwender muss sich nach wie vor einiger Dinge bewusst sein, das gestehe ich dir gerne zu. Aber zb den Schlendrian des 'Fehlerbehandlung kommt später' kannst du mit einer Klasse wirkungsvoll abstellen. Und genau an diesem Punkt kranken viele C Programme (inklusive meiner eigenen).
Dann reservier am Anfang des Programms halt einen Speicherblock mit unsigned char mem[BLOCK_LEN] und verwalte den Speicher dort selbst. Jeder neue String bekommt dann x byte fix von dem Block zugewiesen, ab einem gewissen Offset. Die Operatoren, die man so kennt, wie operator= oder operator+= greifen dann halt auf den zugewiesenen Speicher zu. In einer statischen Variable merkst du dir, welche Memory Blöcke schon belegt sind. Im CTOR werden die Blöcke belegt, im DTOR freigegeben. Der Einfachheit halber bekommt jeder String gleich viel Speicher (z.B. 50byte), das verhindert auch die Fragmentierung. Klar, sehr flexibel ist das ganze nicht, aber du kommst ohne new/delete aus und bist sehr flott weil du nur mit statischen Arrays+Indizes/Offsets arbeitest. Außerdem kannst du die Klasse ja sehr gut an deine Anwendung anpassen. Also so in der Art: [...............][...............][...............] usw... String 1 nicht belegt String 2
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.