Konvertierung von 'size_t' nach 'int', Datenverlust möglich (Split aus: Extremnekromantie)



  • Hallo zusammen,
    ich ich habe die aufgabe bekommen meine Warnungen zu beheben und das macht mir Probleme, ich habe etwa 19 Warnungen C4267 wo mir geagt wird das eine Konvertierung von int nach size_t Datenverlust bereiten kann.

    Damit ich die Fehler beheben kann muss ich das Problem verstehen und da ist auch schon schluss.

    size_t ist ein vorzeichenloser Datentyp und ähnelt unsigned int, wenn ich das richtig verstanden habe. Aber wird das automatisch benutzt , denn ich verwende kein size_t.....

    int Client::sendMessage(string strSendBuf)
    {
    	int p_iVal = 0;
    	try
    	{
    		p_iVal = send(m_objSocketClient, strSendBuf.c_str(), strSendBuf.length(), 0);//C4267	"Argument": Konvertierung von "size_t" nach "int", Datenverlust möglich	
    		if (0 <= p_iVal)
    		{
    			p_iVal = 0;
    		}
    		else
    		{
    			m_objDebugOut.debug(0, "Fehler Client.sendMessage");
    			p_iVal = -1;
    		}
    	}
    
    string PaFR2000Scanner::parseTelegram(string strTelegram, string strParameter)
    {
    	string strParaWert;
    	try
    	{
    		// ermittelt die laenge des uebergebenen Parameters
    		int p_iParaLen = (strParameter.length() - 1);  //C4267	"Initialisierung": Konvertierung von "size_t" nach "int", Datenverlust möglich	
    
    		int p_iParaAnfang = 0;
    		// ermittelt die Position des ersten Zeichens des Parameters
    		p_iParaAnfang = strTelegram.find(strParameter);
    		if (-1 != p_iParaAnfang)
    		{
    			// +3, nach Parameter befinden sich 3 Zeichen die nicht benoetigt werden
    			int p_iParaStart = p_iParaLen + p_iParaAnfang + 3;
    			int p_iParaEnd = strTelegram.find(',', p_iParaStart);
    			strParaWert = strTelegram.substr(p_iParaStart, (p_iParaEnd)-p_iParaStart);
    
    			if (2 <= strParaWert.length())
    			{
    				if ('\"' == strParaWert[0])
    				{
    					strParaWert.erase(strParaWert.begin(), (strParaWert.begin() + 1));
    					strParaWert.erase((strParaWert.end() - 1), strParaWert.end());
    				}
    			}
    		}
    	}
    	catch (...)
    

    Ich verstehe das nicht und würde mich freuen wenn mir jemand einen Ansatzpunkt aufzeigen könnte...


  • Mod

    Bitte keine neuen Fragen an uralte Threads anhängen. Das verschwendet die Zeit aller Leser und ist daher extrem unhöflich gegenüber potentiellen Helfern. Ich habe das mal abgetrennt.

    Bitte das richtige Forum wählen. Hier geht es um das Framework MFC (Microsoft Foundation Classes). Du hast ein allgemeines C++-Thema. Das verhindert, das die richtigen Leute die Frage lesen und schränkt daher die Zahl potentieller Helfer sehr stark ein. Ich habe das mal verschoben.

    Bitte eine Frage stellen. Wenn du nichts fragst, dann weiß ein potentieller Helfer nicht, was du überhaupt wissen möchtest. Stattdessen muss er raten, was die Qualität der Antwort senkt. Ich habe mal geraten, was du eventuell wissen möchtest: string::length liefert einen size_t, es ist schließlich eine Größenangabe. Die Länge eines Strings kann auch potentiell wesentlich größer sein als das, was man ein int speichern kann, daher die Warnung. Dass Windows' send einen int als Größenangabe benutzt, dafür kannst du nichts. Musst du halt sicherstellen, dass der string nicht zu groß ist. Sehr wohl kannst du aber etwas dafür, dass du in deinem eigenen Code int für Größenangaben benutzt. Warum? Und was soll das Abziehen der 1? Was soll eine negative Länge sein? Der ganze Parsercode sieht falsch/umständlich aus, aber ich verstehe gar nicht, was er erreichen soll (und die unsinnige ungarische Notation hilft nicht gerade bezüglich Lesbarkeit), daher kann ich es auch nicht verbessern.



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum MFC (Visual C++) in das Forum C++ (alle ISO-Standards) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Hi,

    Du arbeitest wohl mit einem Atart ST (Amiga?) oder einem 64-Bit System. Wie auch immer, jedenfalls ist offensichtlich sizeof( int ) < sizeof( std::size_t ).

    1. Problem:

    send erwartet als 3. Parameter einen int. string::length liefert aber ein size_t.

    Lösung: prüfe ob String zu lange ist. Wenn ja, schicke mehrere Chunks in der passenden Länge, oder werfe eine Exception und caste den dritten Parameter beim Aufruf von send.

    2. Problem:
    Ändere den Typ von p_iParaLen in std::size_t

    mfg Martin



  • mgaeckler schrieb:

    jedenfalls ist offensichtlich sizeof( int ) < sizeof( std::size_t ).

    Mmh?
    Du meinst std::numeric_limits<>::max()?



  • Jockelx schrieb:

    mgaeckler schrieb:

    jedenfalls ist offensichtlich sizeof( int ) < sizeof( std::size_t ).

    Mmh?
    Du meinst std::numeric_limits<>::max()?

    Das ist dann die Folge meiner obigen Aussage:

    wenn sizeof( x1 ) < sizeof( x2 ) dann std::numeric_limits<x1>::max() < std::numeric_limits<x2>::max().

    Jedenfalls gilt das für alle Systeme, die ich kenne.

    VG



  • Echt?
    Ich weiss es nicht, hätte jetzt aber intuitiv gedacht, dass idR sizeof(int) = sizeof(size_t) ist, also size_t einfach ein unsigned int ist.



  • Jockelx schrieb:

    Echt?
    Ich weiss es nicht, hätte jetzt aber intuitiv gedacht, dass idR sizeof(int) = sizeof(size_t) ist, also size_t einfach ein unsigned int ist.

    Auf 32 Bit Systemen vielleicht. Auf allen mir bekannten aktuellen Systemen ist size_t 8 Byte groß und int nur 4.



  • Jockelx schrieb:

    Ich weiss es nicht, hätte jetzt aber intuitiv gedacht, dass idR ...

    Das ist das Problem.

    Immerhin gibst du zu, dass du es nicht weißt.

    Du kannst bei C/C++ nicht von dem Verhalten auf deinem System auf alle anderen Systeme schließen.

    64-Bit Systeme gibt es schon länger (die Symptome sind aber nicht darauf beschränkt)

    mgaeckler schrieb:

    Du arbeitest wohl mit einem Atart ST (Amiga?) ...

    Gerade das waren schon echte 32-Bit Systeme, im Gegensatz zum DOS, das noch 16-Bit war, aber durchaus 32-Bit Adressen (Segment:Offset) hatte



  • DirkB schrieb:

    Das ist das Problem.

    Jau, riiiiesen Problem!!! Atomkraftwerke werden explodieren!
    Ich wusste nicht, das size_t idR nicht nur stets einen grösseren max-Wert hat als int, sondern einen noch grösseren!


  • Mod

    Jockelx schrieb:

    DirkB schrieb:

    Das ist das Problem.

    Jau, riiiiesen Problem!!! Atomkraftwerke werden explodieren!

    Ähh, die Ariane 5 ist wegen so etwas explodiert.



  • DirkB schrieb:

    mgaeckler schrieb:

    Du arbeitest wohl mit einem Atart ST (Amiga?) ...

    Gerade das waren schon echte 32-Bit Systeme [...]

    bis auf den 16-Bit Datenbus der 68000 CPU



  • SeppJ schrieb:

    Ähh, die Ariane 5 ist wegen so etwas explodiert.

    Ähh, nein, ist sie nicht.
    Es geht hier ja nicht um overflows.
    (Bzw. wo genau kann das Problem entstehen, wenn ich weiss, dass mein Typ (size_t) immer einen grösseren max-wert hat, als ein anderer, aber der max-wert noch grösserer ist als angenommen.)

    Im Grunde auch wurscht diese Diskussion, ich fand nur dieses grosskotizge "das ist dein Problem, aber wenigstens gibtst du es zu, wie dumm du bist" so armselig.


  • Mod

    Jockelx schrieb:

    SeppJ schrieb:

    Ähh, die Ariane 5 ist wegen so etwas explodiert.

    Ähh, nein, ist sie nicht.
    Es geht hier ja nicht um overflows.

    Und wenn du Daten verlierst, weil du nicht auf die Möglichkeit eines Overflows achtest, dann ist das für dich kein Problem ähnlicher Art als wenn du Daten verlierst, weil du sie in einen zu kleinen Typ konvertieren möchtest? Willst du dich an der semantischen Feinheit aufziehen, dass noch nie ein Atomkraftwerk wegen exakt diesem Problem explodiert ist, wenn es unzählige Beispiele gibt, bei denen ähnlich wichtige Dinge wegen ähnlicher Probleme explodiert sind?

    Die Erkenntnis die du mitnehmen solltest ist doch, dass diese Probleme, die dir als kleinkarierte Paragraphenreiterei erscheinen mögen, ganz reale Auswirkungen haben können, die sehr sehr relevant sind. Deine Anwendungen werden nicht korrekt funktionieren, wenn du auf so etwas nicht acht gibst, und wenn du etwas wichtiges programmierst, dann wird demzufolge etwas wichtiges nicht funktionieren. Und dann stürzt eine Rakete für 100 Millionen Euro ab, weil jemand es nicht für wichtig genug befunden hat, sauber zu programmieren.

    Was ist, wenn die Nachricht, die der TE hier verschicken möchte, etwas wichtiges steuert? Ist es dann immer noch egal, dass das Programm wer weiß was tut, wenn die Nachricht zu lang ist? Schade, dass du diese wichtige Lektion lieber als persönlichen Angriff auf dich abtust, anstatt daraus zu lernen.



  • Hm, aber das die Typen unterschiedliche Wertebereiche haben und man darauf achten muss, hatte Jockelx doch geschrieben. Die Einzige Unwissenheit war doch, dass es sein kann, dass sizeof(size_t) > sizeof(unsigned int). Daraus mitnehmen sollte man, dass man size_t auch nicht nach unsigend int konvertieren sollte (zumindest nicht ohne extra überprüfungen). Aber für das Problem des TE, der nach int konvertieren will, sollte es wenig unterschied machen, ob sein Ausganstyp size_t oder unsigned int ist. Ob der abzubildende Wert da rein passt, muss er so oder so überprüfen.



  • DirkB schrieb:

    mgaeckler schrieb:

    Du arbeitest wohl mit einem Atart ST (Amiga?) ...

    Gerade das waren schon echte 32-Bit Systeme, im Gegensatz zum DOS, das noch 16-Bit war, aber durchaus 32-Bit Adressen (Segment:Offset) hatte

    Der ST hatte einen 16-Bit Datenbus. Daher wurde dort das int ebenfalls mit 16 Bit definiert. Intels 32-Bit Systeme hatten mit Ausnahme vom 386SX einen 32-Bit Datenbus. Daher wurden dort ints mit 32 Bit definiert.

    VG



  • SeppJ schrieb:

    Und wenn du Daten verlierst

    Ich verliere keine Daten, wenn ich einen kleineren Typen in einen grösseren konvertiere, insbesondere dann nicht, wenn der grössere Typ noch grösser ist, als ich dachte.

    Schlangenmensch schrieb:

    Hm, aber das die Typen unterschiedliche Wertebereiche haben und man darauf achten muss, hatte Jockelx doch geschrieben.

    Danke fürs lesen.


  • Mod

    Jockelx schrieb:

    SeppJ schrieb:

    Und wenn du Daten verlierst

    Ich verliere keine Daten, wenn ich einen kleineren Typen in einen grösseren konvertiere, insbesondere dann nicht, wenn der grössere Typ noch grösser ist, als ich dachte.

    size_t darf genausogut auch kleiner als int sein. Wichtig ist jedenfalls, dass der Compiler hier nicht grundlos warnt und man dies schon ernst nehmen sollte.



  • SeppJ schrieb:

    size_t darf genausogut auch kleiner als int sein.

    Äh, okay...also sind alle vorherigen Aussagen noch 'falscher' als meine!?
    Hättest du dann aber auch gerne schon vorher mal erwähnen können, hätte uns einiges erspart.

    SeppJ schrieb:

    Wichtig ist jedenfalls, dass der Compiler hier nicht grundlos warnt und man dies schon ernst nehmen sollte.

    Hab ich nie bestritten.



  • SeppJ schrieb:

    size_t darf genausogut auch kleiner als int sein.

    Das würde ich jetzt anzweifeln.

    Aus der Dokumentation:

    size_t can store the maximum size of a theoretically possible object of any type (including array).

    Wenn also sowas erlaubt ist:

    std::array<unsigned int, std::numeric_limits<unsigned int>::max()> testArray;
    

    muss size_t mindestens so groß sein wie int.

    Edit: Mein Beispiel muss aber nicht erlaubt sein, also alles rückgängig!

    Edit 2: Was es aber bedeutet ist, dass es keine Objekte geben kann, die größer sind als durch size_t darstellbar. Also ist man, wenn man irgendwelche Objekte umkopiert oder versendet, mit size_t immer auf der sicheren Seite...


Anmelden zum Antworten