Protokollanleitung als fertiges Paket schreiben



  • Wow, das muss ich erstmal sacken lassen... Ich schreibe erst weiter wenn ich verstanden habe wo meine Fehler waren. Danke Doc



  • Mit dem linksshift war ich ja schonmal nicht ganz so falsch. Auf der rechten Seite des shifts steht die Anzahl N der Bits um die verschoben werden soll...auch noch nachvollziehbar. Ich verstehe das Bitweise OR in seiner Funktion hier einfach nicht



  • Zero01 schrieb:

    Ich verstehe das Bitweise OR in seiner Funktion hier einfach nicht

    Ach, komm´ schon, das ist trivial. Nimm dir´n Blatt Papier und ´nen Stift und mach´ das Ganze ein Mal von Hand. Hier die Wahrheitstabelle für OR, falls das das Problem sein sollte.

    | 0 | 1 |
    ---+---+---+
     0 | 0 | 1 |
    ---+---+---+
     1 | 1 | 1 |
    ---+---+---+
    


  • Danke Doc 👍 hab ein nettes Tutorial zum Thema Bitverschiebung gefunden und weiß jetzt, bezogen auf deine Tips, wie es verwendet wird. Ist im nachhinein auch ne klare Sache wenn ein Wert über mehrere Byte zusammenhängen geschrieben oder gelesen wird. Ich danke dir von ganzem Herzen für deine beispiellose Hilfe. Das Know How durch diesen Thread hat mich ein gutes Stück weiter gebracht



  • Hey Doc!
    ich bin auf ein Problem gestossen. Wenn
    die SequenceID 0x00000001 ist dann baue
    ich mir doch in den stringstream ungewollt einen wertlosen stringterminator ein (0x00)



  • In meinem Code taucht nirgendwo ein stringstream auf, also musst du was dazugebastelt haben.



  • Sorry
    ich meinte den ostringstream



  • Werd´ bitte mal etwas genauer, ich habe keine Ahnung, wo dein Problem liegt.



  • Es geht um folgendes Statement:

    You are using std::strings, and ostringstreams, to construct and contain a sequence of bytes. This works as long as you don't try to put any 0x00 bytes into the sequence. Once you start doing so, you are on very shaky ground.

    Either the resulting sequence will get cut off at the first 0x00 byte, or mystring.size() will be larger than strlen(mystring.c_str()). That way lies madness and bugs that are difficult to track down.

    Besides, you are aware that the 'char' datatype may be either signed or unsigned, depending on which compiler you are using? Normally it is signed. This does not cause any problems for the code that builds the sequence, but may cause problems for the code that decodes a sequence into C++ datastructures.

    You are better off using an std::vector<uint8_t> as your container, dropping the ostringstream, and using some custom code for constructing the sequence.

    Ist diese Aussage richtig oder falsch?



  • Es trifft hier vor allem nicht zu. Es geht darum, dass std::string durchaus Nullbytes enthalten kann und dass std::string::c_str() einen Zeiger auf einen linearen Puffer des Stringinhalts zurückgibt. Damit kommen die C-Funktionen natürlich nicht klar, aber wer Konstruktionen wie

    std::string s = "Mächtiger Badabumm";
    unsigned int len = strlen( s.c_str() );
    

    benutzt hat eh´ nicht mehr alle Latten am Zaun. Du solltest inzwischen gemerkt haben, dass man genau wissen muss, was man programmiert. Wenn du C++ und C Funktionen so mischst, dass Fehler entstehen, dann weißt du´s offensichtlich gerade nicht.
    In dem ganzen Code, den ich hier gepostet habe, tritt der Fall nie auf. Wie kommst du also darauf?



  • Hmmm, ich frage mich gerade warum dieser
    negative Unterton. Ich habe doch nur
    freundlich eine Frage gestellt, zahle
    meine Steuern pünktlich und tuhe auch
    sonst keiner Fliege was zu leide.

    Ich wurde in einem Forum von einem
    User gefragt, ob ich ein C++ Beispiel habe
    um ein Paket mit den gegebenen Anforderungen zu erstellen. Als
    Beispiel habe ich ihm deinen
    unveränderten Code gezeigt ohne
    includes und ohne main().
    Daraufhin hat sich einer der
    Chefentwickler von EA Games
    mit dem oben genannten Statement
    geäussert. Daraufhin fühlte ich
    mich verunsichert und wollte
    dich nochmal Fragen, Gott verzeihe.

    Es geht in keinsterweisse um meinen Code.



  • Ich hab jetzt einen Testcode aufgebaut um sein Statement nachzubilden. Resultat des ganzen ist, dass ich seine Befürchtung mit 0x00 in einem String egal welcher Art theoretisch nachvollziehen kann aber in der Praxis mit deinem Code vollkommen irrelevant ist.

    Er schrieb folgendes:

    // Write Sequence ID
        oss << static_cast<char>( Sequence & 0xff ) 
             << static_cast<char>( (Sequence >> 8) & 0xff ) 
             << static_cast<char>( (Sequence >> 16) & 0xff ) 
             << static_cast<char>( (Sequence >> 24) & 0xff );
    

    That bit right there takes a 32-byte integer, splits it up into 4 bytes, and stuffs each of the 4 bytes into an ostringstream object. Raw. So if Sequence == 0x00000001, the code will be stuffing 0x00's into the ostringstream.

    Also quoting from above,

    // Write terminating 0 
            oss << static_cast<char>( 0 );
    

    This will clearly stuff an 0x00 into the ostringstream.

    Both these code sections violate the principle: do not stuff 0x00s into strings.

    Darauf hin habe ich folgendes Versucht:

    std::vector<std::string> Words;
    Words.push_back("login.plainText");
    Words.push_back("mypassword");
    std::string Packet = make_packet( 0x00000001, Words );
    

    .....funktioniert.

    std::string Packet = make_packet( 0x00, Words );
    

    ....funktioniert

    std::string Packet = make_packet( 1, Words );
    

    .....funktioniert.



  • Zero01 schrieb:

    Ist diese Aussage richtig oder falsch?

    Beides.

    std::string kann mit Nullbytes umgehen und wird auch so verwendet. Auch in gängiger C++ Fachliteratur (z.B. Scott Meyers) steht nichts darüber, dass man das nicht tun soll.

    Was dieser angebliche "Chefprogrammierer" da schreibt:

    Zero01 schrieb:

    Both these code sections violate the principle: do not stuff 0x00s into strings.

    ist eine hausinterne Regel, die jemand braucht, der so etwas wie

    unsigned int len = strlen( s.c_str() );
    

    schreibt.

    Dass der, wie DocShoe schreibt, nicht alle Latten am Zaun hat, ist Realität und kein negativer Unterton.

    Auch C-Strings können Nullbytes enthalten:

    char* pc = "ABC\0abc";
    

    Es gibt genügend Anwendungen, wo das vorkommt. Was mach der "Chefprogrammierer" dann ?



  • Jetzt fühl´ dich nicht gleich auf den Schlips getreten, ich habe weder behauptet, dass du Steuern hinterziehst noch irgendwie anders kriminell bist.
    C++ ist nun mal ein Sprache, die Vieles erlaubt und damit auch viele Möglichkeiten bietet, etwas falsch zu machen. Deshalb schrieb ich ja schon mehrmals, dass man genau wissen muss, was man tut. Wenn ich weiß, dass eine Sequence Binärdaten enthält, dann sollte ich da kein strlen draufloslassen, weil eben genau der Fall eintreten kann, dass irgendwo mittendrin Nullbytes stehen. Und dann liefert strlen nicht das zurück, was man haben will. Für jedes Problem das richtige Werkzeug, und in diesem Fall ist strlen nicht das richtige Werkzeug. Im übrigen geht

    std::vector<uint_8t> MyVec = ...;
    unsigned int len = strlen( &MyVec[0] );
    

    genauso in die Hose, wenn der Vektor Nullbytes in der Mitte enthält.

    Der EA Chefprogrammierer assoziiert mit std::string wohl ein gekapseltes C-String Pendant. Dabei ist std::string wesentlich mächtiger als C-Strings, und das habe ich in meinem Code bewusst ausgenutzt. Du kannst stattdessen natürlich auch einen std::vector<unsigned char> benutzen, wenn es dir besser gefällt:

    std::vector<char> Buffer;
    std::string Word;
    
    Buffer.push_back( static_cast<char>( SequenceID & 0xff ) );
    Buffer.push_back( static_cast<char>( SequenceID >> 8) & 0xff );
    Buffer.push_back( static_cast<char>( SequenceID >> 16) & 0xff );
    Buffer.push_back( static_cast<char>( SequenceID >> 24) & 0xff );
    Buffer.insert( Buffer.end(), Word.begin(), Word.end() );
    
    ...
    

    aber da gefällt mir das ostream Interface wesentlich besser.

    Mit gleichem Argument könnte ich die Benutzung von iteratoren verbieten, da dieser Code zwar kompiliert, aber zu UB führt, was ziemlich knifflig zu debuggen ist:

    std::vector<int> v =...;
    std::sort( v.end(), v.begin() );
    


  • Danke Jungs für die Aufklärung. Jetzt
    wo ich dagegen argumentiert habe, hüllt
    sich dieser Mensch in schweigen.

    Die Aufruf um den std::string als
    konstanten c_string zu lesen
    um die strlen zu bestimmen is eh unfug.
    Wofür haben wir dann das Bordmittel
    .size() was keinerlei Sprachvermischung
    benötigt.

    Nichts für ungut, ich war doch gar nich
    sauer.



  • Danke Jungs für die Aufklärung. Jetzt
    wo ich dagegen argumentiert habe, hüllt
    sich dieser Mensch in schweigen.

    Die Aufruf um den std::string als
    konstanten c_string zu lesen
    um die strlen zu bestimmen is eh unfug.
    Wofür haben wir dann das Bordmittel
    .size() was keinerlei Sprachvermischung
    benötigt.

    Nichts für ungut, ich war doch gar nich
    sauer.


Anmelden zum Antworten