Huge Zahlenklasse mit RSA Absturz bei deconstructor
-
Der Trick an Vector (oder eigenen Ressourcenklassen) ist ja gerade, dass auch diese für die Anwendungsklassen die Rule of 0 ermöglichen
-
@SeppJ sagte in Huge Zahlenklasse mit RSA Absturz bei deconstructor:
Der Trick an Vector (oder eigenen Ressourcenklassen) ist ja gerade, dass auch diese für die Anwendungsklassen die Rule of 0 ermöglichen
Ja stimmt, so hab ich das nicht gesehen. Mein Bild davon war eher, dass es immer noch beachtet werden muss, aber es eben "jemand anderes" bereits gemacht hat... für die
std::vector
verwendende Klasse ist das natürlich dennoch Rule of Zero
-
Habe jetzt Speicher Zuordnung in eine extra klasse gepackt:
template<> class array<unsigned char> { public: array() { _buf = nullptr; _size = 0; _length = 0; }; array(array const& t) { _buf = nullptr; _size = t.size(); _length = t.length(); write(t.c_str(), t.size()); }; virtual ~array() { delete[] _buf; } array operator=(const unsigned char t) { clear(); _buf = new unsigned char[1]; _buf[0] = t; _size = 1; _length = 1; return *this; }; void write(const unsigned char* t, unsigned long size) { if ((_size-_length) < size) { resize((_length+size)); } if(_length>0) memcpy(_buf+(_length-1),t,size); else memcpy(_buf,t, size); _length += size; } array operator=(array t) { clear(); write(t.c_str(), t.size()); _length = t.length(); _size = t.size(); return *this; } unsigned char& operator[](int pos) { return _buf[pos]; }; void resize(size_t size) { if (_length > size) { return; } unsigned char* tmp = _buf; _buf = new unsigned char[size]; memcpy(_buf,tmp,_length); _size = size; delete[] tmp; } size_t size() const { return _size; }; size_t length() const { return _length; } void push_back(char t) { if (_size-_length < 1) { resize(_length + 1); } _buf[_length] = t; ++_length; }; void clear() { delete[] _buf; _size = 0; _length = 0; _buf = nullptr; }; constexpr const unsigned char* c_str() const noexcept { return _buf; }; size_t length() { return _size; }; bool empty() { if (!_buf) return true; return false; } private: unsigned char* _buf; size_t _size; size_t _length; };
leider bekomme ich bei resize folgenden Fehler:
libc.so.6!__memmove_avx_unaligned_erms() Line 254 C++
-
fehler gefunden:
array(array const& t) { _buf = nullptr; _size = t.size(); _length = t.length(); write(t.c_str(), t.size()); };
zu
array(array const& t) { _buf = new unsigned char[t.size()]; memcpy(_buf,t._buf,t.length()); _size = t.size(); _length = t.length(); };
-
@Tuxist1
Und warum nutzt du nicht std::array oder std::vector?
-
@Tuxist1
Ich habe noch ein paar Fragen/Anmerkungen bezüglich deinerarray
Implementierung:- Ist dein
array
eigentlich nicht einstd::basic_string
? Wenn ja, warum spezialisierst du dann das Template? - Wo ist dein Move Konstruktor und deine Move Zuweisung?
- Warum allokierst du ständig einen neuen Puffer, wenn du ein Zeichen hinzufügst? Nehmen wir mal an, du möchtest ein Bild der Größe 1920x1280 einlesen. Dann würde deine Klasse 1920x1280 = 2457600 Allokationen durchführen. Ein std::vector führt unter VS 2019 in diesem Fall aber nur um die 40 Allokationen aus. Warum? Weil gilt "Neue Containergröße = Alte Containergröße * 1.5"
- Wie sieht es mit deiner Exception Safety aus? (Stichwort Copy-Swap Idiom)
- Solltest du da nicht auch noch eine Small String Optimization implementieren?
- Wird eine leere Instanz gelöscht, so rufst du die Funktion
delete
mit einemnullptr
auf.
- Ist dein
-
Es gibt einen zweiten branch wo ich noch die libc mit implementiere kann deshalb kein std:: einbinden kann da std:: wiederum von der libc abhängig ist.
Das hier ist nur mein testbranch.
-
@Tuxist1 sagte in Huge Zahlenklasse mit RSA Absturz bei deconstructor:
Es gibt einen zweiten branch wo ich noch die libc mit implementiere kann deshalb kein std:: einbinden kann da std:: wiederum von der libc abhängig ist.
Was verwendet denn der
operator new
bei dir unter der Haube? Üblicherweise baut der aufmalloc
auf und das ist für gewöhnlich Teil derlibc
. Alles natürlich nicht obligatorisch, letztendlich kann man sich das alles beliebig zusammenstöpseln.Wenn du also irgendwo eine
malloc
-Implementierung hast, dann ist das meiner Einschätzung nach alles was einstd::vector
oder einstd::basic_string
brauchen. Ich weiss allerdings nicht, wie gut sich diese Klassen aus deiner C++-Standardbibliothek isolieren lassen, wennmalloc
/free
alles ist, was man hat und der Rest derlibc
fehlt. Dielibstdc++
hab ich jedenfalls bisher immer mit einer vorhandenenlibc
gebaut. Vielleicht lohnt es sich das mal zu recherchieren. Eventuell auch mallibc++
anschauen. Die ist nicht so alt und könnte eventuell solche etwas unorthodoxeren Setups besser unterstützen.
-
Die Frage ist auch um was für eine (Hardware) Platform es sich hier handelt, und was der Grund ist, das auf eine libc (um welchen denn überhaupt?) verzichtet werden muss.
-
@Finnegan sagte in Huge Zahlenklasse mit RSA Absturz bei deconstructor:
Wenn du also irgendwo eine
malloc
-Implementierung hast, dann ist das meiner Einschätzung nach alles was einstd::vector
oder einstd::basic_string
brauchen.Nein, da kommt einiges an Abhängigkeiten zusammen. Das fängt damit an, dass die Container nicht malloc nutzen sondern std::allocator<T>, und dann kommen da so Abhängigkeiten wie die Traits-, Exception-, … -Header dazu.
-
Noch ein Tipp von mir: Arbeite dich in Unittests ein und teste deine Module ( z.B. dein Array ) einzeln ab. Unittests sind ein wirksames mittel gegen solche Fehler wie bei deinem Resize.
Und selbst wenn du kein Test-Framework aus irgendwelchen Gründen verwenden kannst, kannst du trotzdem Unittests programmieren, denn letztendlich prüfst du nur Rückgabewerte oder Stati von irgendwelchen Variablen und dazu braucht es nicht zwingend ein Framework wie gtest oder anderes.
-
@john-0 sagte in Huge Zahlenklasse mit RSA Absturz bei deconstructor:
@Finnegan sagte in Huge Zahlenklasse mit RSA Absturz bei deconstructor:
Wenn du also irgendwo eine
malloc
-Implementierung hast, dann ist das meiner Einschätzung nach alles was einstd::vector
oder einstd::basic_string
brauchen.Nein, da kommt einiges an Abhängigkeiten zusammen. Das fängt damit an, dass die Container nicht malloc nutzen sondern std::allocator<T>, und dann kommen da so Abhängigkeiten wie die Traits-, Exception-, … -Header dazu.
Ich meine damit schon externe Abhängigkeiten. Der Default-Allocator
std::allocator<T>
dürfte mit demmalloc
derlibc
implementiert sein und bei den anderen genannten Headern sehe ich nicht, was die aus derlibc
brauchen sollten. Exception Handling könnte eventuell Unterstützung einer (externen) Compiler-Runtime benötigen, die auch wiederum Abhängigkeiten haben kann. So genau weiss ich das nicht. Wie ich schon sagte, es is möglich, dass sich das je nach Implementierung der C++-Standardbibliothek alles nicht so leicht voneinander trennen lässt, aber ich sehe nicht wie einstd::vector
inklusive aller Abhängigkeiten grundsätzlich mehr als diemalloc
-Implementierung aus derlibc
benötigen sollte.
-
@Finnegan sagte in Huge Zahlenklasse mit RSA Absturz bei deconstructor:
Der Default-Allocator
std::allocator<T>
dürfte mit demmalloc
derlibc
implementiert sein …Ja, es ist eine der Möglichkeiten, aber es gab/gibt hinreichend viele Compiler die unter UNIX/Linux (keine Ahnung wie die API auf anderen Plattformen aussieht) direkt brk/sbrk nutzen. Und die ganzen Header sollte man auch nicht unterschätzen, weil man sie ggf. erst einmal implementieren muss.
-
@john-0 sagte in Huge Zahlenklasse mit RSA Absturz bei deconstructor:
@Finnegan sagte in Huge Zahlenklasse mit RSA Absturz bei deconstructor:
Der Default-Allocator
std::allocator<T>
dürfte mit demmalloc
derlibc
implementiert sein …Ja, es ist eine der Möglichkeiten, aber es gab/gibt hinreichend viele Compiler die unter UNIX/Linux (keine Ahnung wie die API auf anderen Plattformen aussieht) direkt brk/sbrk nutzen. Und die ganzen Header sollte man auch nicht unterschätzen, weil man sie ggf. erst einmal implementieren muss.
brk
/sbrk
/mmap
sind schon ziemlich low-level, erstere mehr wie ne Stack-Allokation und letzteres auf Speicherseiten-Ebene. Da bräuchte es auf jeden Fall noch ne generische Speicherverwaltung obendrauf die etwas platzeffizienter für beliebige angeforderte Größen ist und den Speicher auch sinnvoll freigeben und wiederverwenden kann. Eben sowas wiemalloc
. Die genannten Compiler müssten dann sowas selbst mitbringen.Ich wollte es aber nicht zu sehr abschweifen lassen. Eigentlich war ich ja hauptsächlich neugierig, wo bei @Tuxist1 der
operator new
herkommt ohnelibc
. Kann man natürlich auch separat einbauen.
-
@Tuxist1 sagte in Huge Zahlenklasse mit RSA Absturz bei deconstructor:
Es gibt einen zweiten branch wo ich noch die libc mit implementiere kann deshalb kein std:: einbinden kann da std:: wiederum von der libc abhängig ist.
Sorry das ich da mal nachhake.
Aber ich verstehe nicht warum man libc bzw. STL nicht nutzen möchte.
In der STL steckt eine Menge Hirnschmalz und lässt sich nicht so einfach nachprogrammieren. Deine array Implementierung mit
c_str()
Funktion z.B. sieht unter Visual Studio folgendermaßen aus:https://github.com/microsoft/STL/blob/main/stl/inc/xstring
Und wo ich gerade in deinem Repo eine Datei namens
atomic.cpp
sehe, möchte ich dir auch die Visual Stdio Variante zeigen:https://github.com/microsoft/STL/blob/main/stl/inc/atomic
8000 LOC, Holla die Waldfee
-
Und dass keine libc verwendet wird ist aktuell nicht korrekt.
z.b. werden folgende header in verschiedenen cpp dateien inkludiert:
- stdint.h (z.b. https://tuxist.de/git/jan.koester/systempp/-/blob/without-libc/src/systempp.cpp)
- stdlib.h (https://tuxist.de/git/jan.koester/systempp/-/blob/without-libc/src/systempp.cpp)
- stdio.h (https://tuxist.de/git/jan.koester/systempp/-/blob/without-libc/src/exception.cpp)
Wobei eventuell der Plan ist, diese durch eine eigene Implementierung zu ersetzen?
Wenn es nicht gerade aus reiner spielerei/wissbegierde ist, sollte man das tunlichst vermeiden so was selbst zu implementieren.
-
in dem main branch wird libc mit implementiert:
https://tuxist.de/git/jan.koester/systempp/-/tree/main
habe einen zweiten branch der mit standart libc gebaut wird:
https://tuxist.de/git/jan.koester/systempp/-/tree/without-libc
wollte erstmal in den zweiten tree https einbauen damit das backend von meinem Blog
"http://tuxist.de" wieder funktioniert hat mit den cookie richtlinien zu tun.Aber jetzt mal zu systempp soll die basis von fenriros bilden, im moment bin ich unzufrieden über den wildwuchs von unix/linux konfiguartions Dateien jeder und alles macht da was er will führt dazu das es unnötig viel Arbeit konfigurations Oberflächen dafür zu schreiben. Das zweite Problem was ich sehe ist das man auf tiefere ebene zum teil sehr schwerig zu verstehende api hat und meist nur auf c ebene. Ich versuche da Abhilfe zu schaffen da ich als Rentner jetzt zeit dafür habe.
Unterschiede Fenriros zu anderen Posix Systemen:
-confdb mit conffs eine art registry
-sid statt fortlaufender uid's nt kompatible
-vollständige C++ ABI
-bsd lizens
-keine gnu abhängikeitenNach dem https implementiert werde ich mich wieder meinem elfparser widmen damit ich endlich in System chrooten kann und danach stdio implementieren danach noch paar kleine posix geschichten damit hoffentlich llvm unter der chroot kompeliert der basis Compiler für das System. Danach Feinit damit ich ein init system habe und CMake support für Linux Kernel und Python.
-
@Tuxist1 sagte in Huge Zahlenklasse mit RSA Absturz bei deconstructor:
Ich versuche da Abhilfe zu schaffen da ich als Rentner jetzt zeit dafür habe.
Wenn ich so deinen letzten Beitrag lese, habe ich das Gefühl dass du dich übernimmst. Die Libc nachzuprogrammieren ist keine kleine Sache, ebenso Verschlüsselung und erst Recht nicht eine Grundlage eines Betriebssystems.
Aus meiner Sicht wäre das Aufgabe eines kleinen Entwicklungsteams für die nächsten X Jahre.
-
@Quiche-Lorraine da hast du recht bin ich schon 4 Jahre bei spalte immer wieder Sachen ab die ich auch so gebrauchen kann, das hält meine Motivation am laufen. Das schöne ist mal lernt unheimlich viel.