null in std::string -> UB oder OK?



  • Dobi sagt:

    In einem kleinen TCP/IP-Protokoll, dessen Tokens in meiner Software als Strings rumgereicht werden, kommt nun die (unnötige) Anforderung hinzu, dass an einer Stelle ein redundantes '\0' hinten dran sein muss.

    Da bei TCP/IP fast immer irgend eine API aufgerufen wird ist IMHO das Wort "unnötig" zurecht in Klammern.

    std::string.c_str() doku sagt:

    This array includes the same sequence of characters that make up the value of the string object plus an additional terminating null-character ('\0') at the end.

    Also macht std::string.c_str() genau das was Dobi will.



  • weicher schrieb:

    Da bei TCP/IP fast immer irgend eine API aufgerufen wird ist IMHO das Wort "unnötig" zurecht in Klammern.

    Naja, wenn ein Token so aussehen soll:

    Startzeichenfolge
    char[3] -> Anzahl Zeichen
    char[n] -> Zeichen
    \0
    Endzeichenfolge
    

    finde ich die null schon ziemlich unnötig. Ich würde normal entweder die Anzahl Zeichen vorwegschicken oder nullterminieren, aber nicht beides.

    weicher schrieb:

    Also macht std::string.c_str() genau das was Dobi will.

    Nö, selbst wenn das gehen würde, würde sich die Seuche dann ja auch in den Rest des Programms ausbreiten, weil ich mit char* hantieren müsste. Mit der andereren Lösung bleiben schön alles ein String, nur dass manchmal halt '\0' drin vorkommt, was mich im Rest vom Code aber nicht interessieren muss. Ich finde das so wesentlich schicker.



  • Nö, selbst wenn das gehen würde, würde sich die Seuche dann ja auch in den Rest des Programms ausbreiten, weil ich mit char* hantieren müsste.

    Nein, so habe ich das nicht gemeint.

    Du kannst im ganzen Programm ganz normal mit dem std::string arbeiten ohne dieses gefrickel mit dem anhängen einer '\0'.

    Dann must Du nur genau dort wo ein NULL terminierter string verlangt wird den std::string.c_str() verwenden. Das ist übrigends keine Seuche 😉 die meisten API's verwenden const char* oder char* und genau zu diesem Zweck hat std::string die Funktion c_str()



  • Mal ganz banal:

    #include <string>
    #include <iostream>
    
    std::string frame(const std::string& s)
    {
    	return std::string("start") + s + "ende";
    }
    
    std::string generateNormal()
    {
    	return "huhu";
    }
    
    std::string generateFrickelMist()
    {
    	std::string s("003bla_");
    	s.back() = '\0';
    	return s;
    }
    
    std::string generate()
    {
    	bool cond( false );
    	auto s = cond ? generateNormal() : generateFrickelMist();
        return frame(s);
    }
    
    void send(const std::string& s)
    {
        // Druecks ins Socket.
    	std::cout << s << "\n";
    }
    
    int main()
    {
        for(;;)
        {
            auto s = generate();
            send( s );
        }
    }
    

    Wie wär das jetzt mit std::string.c_str() schöner?



  • Nee, wird nicht schöner 😉

    Ich bin davon ausgegangen, dass Du eine struct für einen API Aufruf ausfüllen musst.



  • Arcoth schrieb:

    Es ist nicht definiert, dass s.c_str() == &s[0] .

    Doch.

    (Ja, in C++03 ist es nicht explizit definiert, aber de facto eben doch)



  • Die C++-Programmiersprache §20.3.7 schrieb:

    [...]im von c_str() oder data() reservierten Puffer[...]


  • Mod

    c++11 schrieb:

    Doch.

    Ja, das stimmt, seit C++11:

    const charT* c_str() const noexcept;
    const charT* data() const noexcept;
    

    Returns: A pointer p such that p + i == &operator[](i) for each i in [0,size()] .

    In C++03 war das zwar in den Implementierungen praktisch immer der Fall, war aber nicht garantiert.


  • Mod

    §20.3.7

    So einen Paragraphen gibt es nicht 😕 21.3.7 genauso wenig.



  • Hallo Doby,

    std::string generateFrickelMist() 
    { 
         std::string s("003bla_"); 
         s.back() = '\0'; 
         return s; 
    }
    

    könntest Du auch so machen:

    std::string generateFrickelMist() 
    { 
         std::string s("003bla"); 
         s.push_back('\0'); 
         return s; 
    }
    


  • Oh stimmt, das ist hübscher, danke.



  • Arcoth schrieb:

    §20.3.7

    So einen Paragraphen gibt es nicht 😕 21.3.7 genauso wenig.

    Die C++-Programmiersprache §20.3.7


  • Mod

    Whups! Ich habe gar nicht geschaut, auf was sich das bezieht 🙂


Anmelden zum Antworten