{"id":187,"date":"2008-01-08T22:05:11","date_gmt":"2008-01-08T21:05:11","guid":{"rendered":"http:\/\/blog.m-ri.de\/index.php\/2008\/01\/08\/die-unsitte-objekte-direkt-in-printf-und-funktionen-mit-variabler-anzahl-von-argumenten-zu-nutzen\/"},"modified":"2008-04-02T21:08:29","modified_gmt":"2008-04-02T19:08:29","slug":"die-unsitte-objekte-direkt-in-printf-und-funktionen-mit-variabler-anzahl-von-argumenten-zu-nutzen","status":"publish","type":"post","link":"http:\/\/blog.m-ri.de\/index.php\/2008\/01\/08\/die-unsitte-objekte-direkt-in-printf-und-funktionen-mit-variabler-anzahl-von-argumenten-zu-nutzen\/","title":{"rendered":"Die Unsitte Objekte direkt in printf und Funktionen mit variabler Anzahl von Argumenten zu nutzen"},"content":{"rendered":"<p>Immer wieder sieht man Code wie diesen:<\/p>\n<pre line=\"1\" lang=\"cpp\">CString strText = _T(\"xyz\"); \r\n_tprintf(_T(\"Irgendwas ist %s und jetzt kommt eine Zahl %d\"), \r\n                           strText, 4711);<\/pre>\n<p>Sieht harmlos aus und funktioniert. Warum eigentlich?<\/p>\n<p>Es funktioniert nur aus einem einzigen Grund:<br \/>\n<em>CString<\/em> ist 4 Bytes gro\u00df, besteht nur aus einem einzigen Element und das ist ein Zeiger auf einen <em>TCHAR<\/em> Array!<\/p>\n<p>Das ganze funktioniert sofort nicht mehr wenn wir eine eigene <em>CMyString<\/em> Klasse ableiten, der wir eine virtuelle Funktion zuordnen. Was passiert nun?<br \/>\nNun ist <em>CString<\/em> nicht mehr 4 Bytes gro\u00df sondern 8 Bytes und besteht aus zwei Zeigern. Einem Zeiger auf eine <em>vtable<\/em> und einen Zeiger auf einen <em>TCHAR<\/em> Array.<\/p>\n<p>Nicht nur wird jetzt kein Text mehr ausgegeben, sondern auch die Zahl wird nicht korrekt ausgegeben! Das ganze obwohl <em>CMyString<\/em> immer noch einen Umwandlungsoperator f\u00fcr <em>LPCTSTR<\/em> hat.<\/p>\n<p>Das Problem ist aber, dass _<em>tprintf<\/em> eine Variable Anzahl von Argumenten (Ellipsis) hat und der C\/C++ Compiler gar nicht wei\u00df, was _<em>tprintf<\/em> erwartet. Also wird das ganze Objekt auf den Stack geschoben.<\/p>\n<p>Man macht eine kleine \u00c4nderung, und schon geht die Sache in die Hose. Das habe ich ja schon in dem Artikel <a href=\"http:\/\/blog.m-ri.de\/index.php\/2007\/09\/12\/die-cx2y-falle\/\">Die Cx2y Falle<\/a> beschrieben. Oder sollte also so etwas wie eine \u00c4nderung der Implementierung von <em>CString<\/em> erfolgen w\u00fcrde solch ein Programm auch sofort nicht mehr funktionieren. Man muss jedoch vermuten, dass Microsoft sich das gar nicht erlauben w\u00fcrde, weil zu viele Entwickler solchen nicht portablen und unabh\u00e4ngigen Code verwenden.<\/p>\n<p>Wie macht man es richtig? Man verwendet den entsprechenden cast oder eine Funktion, die den entsprechenden Typ returniert.<\/p>\n<pre line=\"1\" lang=\"cpp\">CString strText = _T(\"xyz\"); \r\n_tprintf(_T(\"Irgendwas ist %s und jetzt kommt eine Zahl %d\"), \r\n                       static_cast&lt;LPCTSTR&gt;<lpctstr><\/lpctstr>(strText), 4711); \r\n\/\/ -- oder -- \r\n_tprintf(_T(\"Irgendwas ist %s und jetzt kommt eine Zahl %d\"), \r\n                       strText.GetString(), 4711);<\/pre>\n<p>Man sollte grunds\u00e4tzlich bei der Verwendung von einer variablen Anzahl von Argumenten (Ellipsis) immer auf den Typ casten, der auch letzten Endes erwartet wird.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Immer wieder sieht man Code wie diesen: CString strText = _T(&#8222;xyz&#8220;); _tprintf(_T(&#8222;Irgendwas ist %s und jetzt kommt eine Zahl %d&#8220;), strText, 4711); Sieht harmlos aus und funktioniert. Warum eigentlich? Es funktioniert nur aus einem einzigen Grund: CString ist 4 Bytes gro\u00df, besteht nur aus einem einzigen Element und das ist ein Zeiger auf einen TCHAR &hellip; <a href=\"http:\/\/blog.m-ri.de\/index.php\/2008\/01\/08\/die-unsitte-objekte-direkt-in-printf-und-funktionen-mit-variabler-anzahl-von-argumenten-zu-nutzen\/\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eDie Unsitte Objekte direkt in printf und Funktionen mit variabler Anzahl von Argumenten zu nutzen\u201c <\/span>weiterlesen<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[25,30,19,4,3,2],"tags":[370,352,74,61],"class_list":["post-187","post","type-post","status-publish","format-standard","hentry","category-atl","category-c","category-crt","category-mfc","category-programmieren","category-windows-api","tag-c","tag-mfc","tag-unsitten","tag-winapi"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/187","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/comments?post=187"}],"version-history":[{"count":0,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/187\/revisions"}],"wp:attachment":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/media?parent=187"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/categories?post=187"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/tags?post=187"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}