Speicher Problem

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Speicher Problem

    Hi!
    Ich will folgendermaßen ein char-array in eine Funktion speichern:

    Quellcode

    1. fstream f;
    2. TStringList *List = new TStringList;
    3. List->LoadFromFile("test.txt");
    4. f.open("test.dat", ios::out);
    5. for(int i=0; i < List->Count-1; i++)
    6. {
    7. char *buffer = new char[List->Strings[i].Length()];
    8. buffer = List->Strings[i].c_str();
    9. f.write((const char *)buffer,List->Strings[i].Length());
    10. delete [] buffer;
    11. }
    12. f.close();
    Alles anzeigen

    Jetzt tritt aber das Problem auf das beim Aufruf die Meldung "Zugriffsverletzung..."kommt...
    es muss was mit dem buffer zu tun haben, aber wie kann ich das anders machen?
    Ich brauch die Strings aus der StringList als chars da ich später vor dem speichern eine XOR verschlüsselung anwenden will...

    kann mir jemand helfen??
    Schonmal vielen Dank!!!!!!

    MfG Straightflush
  • Und noch was, c strings sind 0 terminiert, sprich um die korrekt in nen speicher zu bekommen, brauchen die anzahl der zeichen + 1 fuer den terminator an platz.

    Noch was allgemeines:

    du verwendest new und c (string)befehle fuer standardoperationen, wo du locker mit c++ klassen hinkommen wuerdest.

    entweder c, dann malloc statt new und FILE * statt fstream , oder c++ dann bitte mit std::string (std::basic_string<char>) arbeiten.

    Was du machst, iss mischmasch

    Ciao ....

    Quellcode

    1. fstream f;
    2. TStringList *List = new TStringList;
    3. List->LoadFromFile("test.txt");
    4. f.open("test.dat", ios::out);
    5. for(int i=0; i < List->Count-1; i++)
    6. {
    7. f << List->Strings[i]; // das c_str() deutet darauf hin, das das sowieso nen std::string ist was dahinter steht
    8. }
    9. f.close();
  • grmml, ok ja, ich habs uebersehen :)

    Auch hier die frage wieder, warum die liste dynamisch anlegen ?
    Die elemente in der liste werden sicher eh dynamisch gehalten von der liste selber, aber warum den rumpf der liste aufn heap legen ?

    Quellcode

    1. fstream f;
    2. TStringList list;
    3. list.LoadFromFile("test.txt");
    4. f.open("test.dat", ios::out);
    5. for(int i=0; i < list.Count-1; i++)
    6. {
    7. f << list.Strings[i]; // das c_str() deutet darauf hin, das das sowieso nen std::string ist was dahinter steht
    8. }
    9. f.close();


    gaenge das nich ?

    Ciao ...
  • Du hast imho völlig recht, wenn du versuchst alles auf dem Stack anzulegen, aber es gibt diesbzgl. ein paar Dinge zu bedenken.
    - Der Stack von normalen Windows-Applikationen ist 1 oder 2 MB groß, was nicht sehr viel ist, und es schnell zu einem Stack Overflow kommen kann. Bei großen Applikation ist das sehr relevant!
    - Der Vorteil an der dynamischen Allokation ist, dass ich den Zeitpunkt des Löschens besser bestimmen kann (wenn man von zusätzlicher Klammerung absieht)
    - Jeder Thread hat seinen eigenen Stack und ich weiß nicht, wie gut das sharen von auf dem Stack angelegten Objekten funktioniert

    Im speziellen Fall hast du natürlich recht, und die statische Variable reicht völlig :)
  • Ich hab nie gesagt, das man jedes new eliminieren kann !
    Ich sagte nur das man es sich wirklich reichlich ueberlegen soll. Grad viele Anfaenger verwenden das new viel zu oft, wo es nicht noetig ist.

    Regel: Stack - da wo man kann, Heap - da wo man muss !

    Und ja, die groesse der Daten und die kontrolle ueber die laufzeit koennen einen aufn heap zwingen. (mit Heap mein ich den Freestore inclusive )


    Jeder Thread hat seinen eigenen Stack

    sehr sehr abstract gesehen ja :)
    - Du laeufst im normalen mainthread auf dem "Hauptstack"
    - es kommt das CreateThread
    - der hauptthread laeuft danach auf seinen "Hauptstack" normal weiter.
    - Der neu erzeugte Thread startet an der Startposition der Threadproc (beim createthread angegeben)
    - er bekommt einen total neuen, eignen stack
    - auf den stack liegt eigentlich am anfang nur der weitere uebergabeparameter, was die threadproc uebergeben bekommt, in form eines zeigers (4byte) , damit man ueberhaupt daten vom mainthread auf die erzeugten threads bekommt.
    - ab da an arbeitet der neue thread mit seinem stack normal weiter.
    - jeder erzeugte thread bekommt seinen eigenen stack ....
    - der stackbereich wird vom BS glaub ich geliefert, das sicherstellt das die stacks sich ned ins gehege kommen. wird normalerweise vom speichermanager als einfacher block angefordert.
    - man kann die groesse des stacks fuer threads ueber parameter im rahmen das was das BS kann, einstellen .... (beim mainthread der exe auch, ueber erweiterte startparameter)

    jeder thread muss logischerweisse seinen eigenen Stackbereich haben, weil ... threads in beliebiger reihenfolge creiert und zerstoert werden koennen ...
    Gaenge das auf einen stack, wuerde der fragmentieren .... was jegliche Verwaltung des stacks unterlaufen wuerde.
    Das tolle am stack iss halt, das er linear auf und wieder abgerollt wird, und damit nie fragmentiert ..... wie der name scho sagt, ein stack(stapelspeicher) also ^^

    BTW. Linux kann den stack dynamisch erweitern .... im idealfall kann ich da den ganzen freien arbeitsspeicher als stack verwenden. Ob das sinvoll ist, iss ne andere geschichte.


    Ciao ...
  • "Sussi" schrieb:



    BTW. Linux kann den stack dynamisch erweitern .... im idealfall kann ich da den ganzen freien arbeitsspeicher als stack verwenden. Ob das sinvoll ist, iss ne andere geschichte.


    Ciao ...


    In Linux kannst du sogar _mehr_ als den gesammten Arbeitsspeicher als Stack verwenden. Die größe ist nur durch den Adressraum des Prozessors begrenzt (und durch die swap-partition)
    There are only 10 types of people in the world: Those who understand binary, and those who don't.

    Download meines ersten Spiels:HIER
    Über Feedback würde ich mich freuen ;)
  • erstmal vielen Dank für die Antworten!!!!!!

    das mit strcpy war ein echt guter Tipp
    so funktioniert jetzt das ganze:

    Quellcode

    1. fstream f;
    2. TStringList *List = new TStringList;
    3. List->LoadFromFile("test.txt");
    4. f.open("test.dat", ios::out);
    5. for(int i=0; i < List->Count-1; i++)
    6. {
    7. char *buffer = new char[List->Strings[i].Length()+1];
    8. strcpy(buffer,List->Strings[i].c_str());
    9. f.write((const char *)buffer,List->Strings[i].Length());
    10. delete [] buffer;
    11. }
    12. f.close();
    13. delete List;
    Alles anzeigen

    ch brauche doch aber jedes char kurzzeitig einzeln, so dass ich die verschlüsselung anwenden kann...
    Damit geht es ja nicht:

    Quellcode

    1. fstream f;
    2. TStringList list;
    3. list.LoadFromFile("test.txt");
    4. f.open("test.dat", ios::out);
    5. for(int i=0; i < list.Count-1; i++)
    6. {
    7. f << list.Strings[i]; // das c_str() deutet darauf hin, das das sowieso nen std::string ist was dahinter steht
    8. }
    9. f.close();


    Allerdings möchte ich nocheinmal betonen das ich für die Verschlüsselung die Strings kurzzeitig in einzelnen chars brauche, da jedes einzeln verschlüsselt werden soll...
    Das ich jeden String einzeln in den Stream stecken kann ohne vorher ihn in ein char array zu speichern wusste ich ja...


    entweder c, dann malloc statt new und FILE * statt fstream , oder c++ dann bitte mit std::string (std::basic_string<char>) arbeiten.

    das vor dem Komma verstehe ich noch aber das danach sagt mir ehrlich gesagt recht wenig...
    Hat jemand nen Literatur/Webpage Tipp wo gerade zu dem Thema mehr erklärt wird??
  • So viel ich weiss nicht ....
    Hab mal gelesen das da ne Sperre drinne ist, wegens dem Totswappen.
    Der Stack eines programms kann schon auf ne Auslagerungsseite gesichert werden, aber dann darf das programm ned aktiv sein. Wenns aktiv wird, wirds der Stack eh sofort wieder in den normalen hauptspeicher eingeblendet.

    Theorethisch wuerde es sicher gehen, aber praktisch ist das system dann soweiso schon tot ^^ Spruenge/zeiger aufn stack sind immer lokal, wenn da impliziet nen mechanismus eingebaut werden muss, um zu schauen ob ich die adresse erst von der auslagerungsseite holen muss, ohje, das wuerde programme ziemlich langsam machen. und wenn einer mal hin und herspringt, muesste das system auch hin und herswappen .... koennen aber gerna mal auf anderen foren fragen ....

    100% sicher bin ich mir aber auch ned, sag niemals nie :)

    Ciao ...
  • das ich für die Verschlüsselung die Strings kurzzeitig in einzelnen chars brauche

    Ja ok, deswegen frag ich ja ....

    deine verschluesselungsfunktion existiert die schon, und wenn ja, wie nimmt die deine "chars" entgegen (aufrufsyntax)?

    ne zwischenzeitliche copie machen geht auch in c++, allerdings viel eleganter :)
    std::string ist die c++ stringklasse (der STL, teil des c++ standards). Bei der brauchst dich um speicher allocs nimmer zu kuemmern ....

    Quellcode

    1. fstream f;
    2. TStringList list;
    3. list.LoadFromFile("test.txt");
    4. f.open("test.dat", ios::out);
    5. for(int i=0; i < list.Count-1; i++)
    6. {
    7. // hier mit ner Copie ....
    8. std::string strBuffer(list.Strings[i]);
    9. // hier kannst mit dem "Buffer" nu bisserl was boeses anstellen, beispielsweisse verschluesseln
    10. // Encrypt(strBuffer);
    11. // und verschluesselten text ausgeben
    12. f << strBuffer;
    13. }
    14. f.close();
    Alles anzeigen


    Ist doch viel komfotabler eigentlich ... obs so einfach geht, haengt natuerlich von deiner encrypt funktion ab :)

    Ciao ..
  • ist schon viel komfortabler, aber in gewisser Weise wird da ja mein problem nur auf
    die Verschlüsselungsfunktion übertragen...

    Zur Erläuterung der Verschlüsselung

    ich habe ein integer array welches als schlüssel fungiert und den String der zu verschlüsseln ist

    der erste Buchstabe des Strings wird nun bitweise mit dem ersten Element des Integer Arrays verschlüsselt...

    Dabei werden die Bits verglichen: Sind zwei Bits gleich wird das Bit der verschlüsselten Version 0, andernfalls 1;

    Bsp

    char :0101 1101
    key :1100 1010
    -------------------
    final: 10010111

    Das lässt sich jetzt leider nicht auf den gesamten String anwenden, wo auch schon das Problem liegt...
    Eine weitere Möglichkeit wäre allerdings die Buchstaben einzeln in jeweils ein char zu speichern, dieses zu verschlüsseln und an den finalen String zu hängen...

    Dieses dann Zeichen für Zeichen des Strings...


    Nebenbei: ist char ein Bestandteil von C++ oder ein Überbleibsel von C?

    MfG Straightflush
  • Du meinst also eine einfach XOR Funktion (Operator ^)
    Ja: char ist ein Bestandteil von C++ um ein einzelnes Byte abzudecken.

    Beispiel für eine sehr simple Verschlüsselungsfunktion, die alle Zeichen verschlüsselt:

    Quellcode

    1. string encrypt (const string& s)
    2. {
    3. string result;
    4. for (const char* pSrc = s.c_str (), size_t i = 0; i < s.length (); ++i, ++pSrc)
    5. result += *pSrc ^ 0x44;
    6. return result;
    7. }
  • Hey super danke!
    Nehme eigentlich nicht so gerne schon vorprogrammierte Funktionen aber, aber ich glaube diesmal kann ich eine Ausnahme machen :wink:

    Deine Funktion erscheint sehr logisch, trotzdem kapiere ich sie nicht ganz...
    Was bewirkst du mit

    Quellcode

    1. ++pSrc


    Und wie kannst du den ganzen String auf ein "const char" kopieren?

    Das einzige was ich mir vorstellen könnte wäre das dieses "++" irgendwie ständig das nächste Zeichen nimmt, habe aber leider noch nie von einem derartigen Umgang gehört(soll nicht schlecht klingen)

    Off-Topic:
    Was für Literatur nutzt du in C++? Wie lernst du weiter?Wie hast du dir angelernt was du kannst?
  • 1. Ich weise nicht den String einem const char zu, sondern ich hole mir die Adresse des 1. Zeichens des Strings.
    Beispiel:

    Quellcode

    1. string s("Hallo");
    2. const char* p = s.c_str ();
    3. cout << (*p); // ergibt -> 'H'


    2. per "++" gehe ich zur nächsten Speicheradresse (genau um 1 Byte weiter)

    Quellcode

    1. string s("Hallo");
    2. const char* p = s.c_str ();
    3. cout << (*p); // ergibt 'H'
    4. ++p; // ist in diesem Fall das selbe wie "p++"
    5. cout << (*p); // ergibt 'a'
    6. // usw


    3. Den Unterschied zwischen "++i" und "i++" wird bereits an anderen Stellen breit getreten. Generell ist "++i" um einen Hauch schneller als "i++" - hängt aber vom Compiler ab

    Wichtig in diesem Zusammenhang: Pointer ("const char* pSrc" ist einer)

    @Offtopic: trial und error am Anfang - merken - anwenden - und das für die letzten X Jahre, also keine Sache von 4 Wochen 8)
  • The size_t type is defined in stdio.h, stddef.h, stdlib.h, and string.h. This type is used for defining the sizes of strings and memory blocks. It is defined as:

    Quellcode

    1. typedef unsigned int size_t;


    Eigentlich nicht, kann aber sein, dass es beim BCB mit VCL anders ist.
    ~ mfg SeBa

    Ich beantworte keine PMs zu Computer-/Programmierproblemen. Bitte wendet euch an das entsprechende Forum.

    [Blockierte Grafik: http://i.creativecommons.org/l/by-sa/3.0/80x15.png]
  • Hatte noch nen paar Probleme mit der Funktion aber nachdem ich die Funktion verändert habe gehts

    Hier die Funktion

    Quellcode

    1. string encrypt (const string& s)
    2. {
    3. string result;
    4. const char* pSrc = s.c_str ();
    5. for (unsigned int a = 0; a < s.length (); a++)
    6. {
    7. result += *pSrc^(char)0x044;
    8. ++pSrc;
    9. }
    10. return result;
    11. };
    Alles anzeigen


    und hier wird das ganze gespeichert:

    Quellcode

    1. fstream f;
    2. TStringList *List = new TStringList;
    3. List->LoadFromFile("test.txt");
    4. f.open("test.dat", ios::out);
    5. for(int i = 0; i < List->Count; i++)
    6. {
    7. f << encrypt(List->Strings[i].c_str());
    8. }
    9. f.close();
    10. delete List;


    MfG Straightflush
  • @Phax

    Du verwendest die STL aber sehr .... abstract ^^
    Also mittels Zeiger aufn STL Container rumzurutschen ist schon sehr ungewoehnlich. Manchmal muss man auch ungewoehnliche dinge tun, aber nur wenn man muss.
    Solltest dich echt mal tiefer mit der STL beschaeftigen, wenn du wirklich C++ programmieren willst, Du hasst noch nen ziemlichen C Stil intus :)

    Um einzelne Mitglieder eines Containers (std::string) zu manipulieren und ggf. in nen neuen container zu schreiben, eignet sich am besten nen functor in verbindung mit ner transformation ....
    Ausserdem wenn man deinen Entwurf performancekritisch sieht, wuerd ich zumindest dein result string schon in der passenden groesse aufziehen, nich das der sich immer dynamisch erweitern muss

    Quellcode

    1. std::string encrypt (const std::string& s)
    2. {
    3. // result gleich mit dem original belegen, dann hat er die richtige goresse, keine dynamische laengenanpassung mehr !
    4. std::string result(s);
    5. // Nen functor bauen der nen EInzelnes Zeichen Codiert
    6. // dazu ne klasse ....
    7. // den Wert zum verodern kannst variabel machen und beim COnstructor uebergeben ....
    8. // der einfachheit halber mal lokal deklariert und definiert
    9. class char_encoder
    10. {
    11. public:
    12. char_encoder(char OrValue): mOrValue(OrValue)
    13. {
    14. }
    15. ~char_encoder(){} // kein virtueller CTor, nich fuer vererbung ...
    16. // und die eigentliche Encoder version als Operator
    17. char operator() (const char & rx)
    18. {
    19. return rx^mOrValue;
    20. }
    21. private:
    22. const char mOrValue;
    23. };
    24. // wir wollen mit 0x44 verodern, also nen encoder fuer anlegen
    25. char_encoder encoder(0x44);
    26. // auf den zielstring anwenden, im zielstring steht der alte string scho drinne, also einfach nur transformieren
    27. std::transform(result.begin(),result.end(),result.begin(),encoder);
    28. // das wars
    29. return result;
    30. };
    Alles anzeigen


    So oder ähnlich wuerd ichs in c++ machen.
    Sieht doch viel schoener aus, so ganz ohne die vielen *** :P

    Die Klassendefinition und so kann man sich auch sparen, wenn man bei dem XOR bleibt ... mit nem binder kann man dann auch direkt manipulieren ....

    Quellcode

    1. std::string encrypt (const std::string& s)
    2. {
    3. std::string result(s);
    4. // wir wollen mit 0x44 verodern, also xor verwenden gebunden an die 0x44;
    5. std::transform(result.begin(),result.end(),result.begin(),std::bind2nd(std::xor<char>(),0x44));
    6. // das wars
    7. return result;
    8. };



    (char)0x044;

    und noch bitte 100 mal an die Tafel schreiben:
    C-Casts in C++ sind Boese !
    :twisted:

    Ciao ...