{"id":596,"date":"2011-12-05T22:52:42","date_gmt":"2011-12-05T21:52:42","guid":{"rendered":"http:\/\/blog.m-ri.de\/?p=596"},"modified":"2011-11-30T22:52:58","modified_gmt":"2011-11-30T21:52:58","slug":"die-tucke-mit-temporaren-objekten-und-konvertierungs-operatoren","status":"publish","type":"post","link":"http:\/\/blog.m-ri.de\/index.php\/2011\/12\/05\/die-tucke-mit-temporaren-objekten-und-konvertierungs-operatoren\/","title":{"rendered":"Die T\u00fccke mit tempor\u00e4ren Objekten und Konvertierungs-Operatoren"},"content":{"rendered":"<p>Wieder mal ein Beispiel f\u00fcr einen versteckten Bug.<br \/>\nNachfolgender Code sieht ganz unscheinbar aus, aber er birgt eine Falle mit sich, die in der Implementierung der Klasse verborgen ist:<\/p>\n<pre lang=\"cpp\">void CImageButton::OnSysColorChange()\r\n{\r\n   \/\/ Farbe hat ge\u00e4ndert\r\n   CButton::OnSysColorChange();\r\n   \/\/ Bitmap neu laden\r\n   LoadBitmap(m_strResource.IsEmpty() ? m_lpszResource : m_strResource);\r\n}<\/pre>\n<p><em>LoadBitmap<\/em> ist eine Funktion, die die Bitmap neu l\u00e4dt und entsprechend der eingestellten Systemfarben einige Farben aktualisiet. Also das bekannte Verhalten von Toolbars. <em>LoadBitmap<\/em> nimmt einen LPCTSTR und\u00a0damit kann die <em>CImageButton<\/em> Klasse entweder mit einem Ressource String arbeiten (der evtl. mit MAKEINTRESOURCE eine ID ist und kein echter Zeiger), oder eben einem Namen zu einer Bitmap Ressource.<\/p>\n<p>Damit bei einem Wechsel der Systemfarben, die Bitmap neu laden werden kann, merkt es sich die Resource.\u00a0 In der Funktion findet hier eine Konvertierung des alten <em>CString<\/em> Wertes in einen <em>LPCTSTR<\/em> statt, mit dem eingebauten Konvertierungs-Operator.<\/p>\n<p>Das Problem in der Implentierung dieser Klasse war aber, dass <em>LoadBitmap<\/em> sich den neuen Ressourcennamen merken soll aber zuvor eine interne <em>Clear<\/em> Funktion aufruft, die die bestehende Bitmap und andere Klassendaten freigibt, bevor <em>m_strResource<\/em> oder <em>m_lpszResource<\/em>, neu gesetzt werden:<\/p>\n<pre lang=\"cpp\">void CImageButton::Clear()\r\n{\r\n  ...\r\n  \/\/ Clear old infos\r\n  m_lpszResource = NULL;\r\n  m_strResource.Empty();\r\n  ...\r\n}\r\n\r\nbool CImageButton::LoadBitmap(LPCTSTR pszResource)\r\n{\r\n   Clear();\r\n...\r\n   if (ISINTRESOURCE(pszResource))\r\n...\r\n   else\r\n   {\r\n       m_strResource = pszResource;\r\n...\r\n   }\r\n...\r\n}<\/pre>\n<p>Das f\u00fchrt aber nun zu folgendem Problem: <em>Clear<\/em> l\u00f6scht <em>m_strResource<\/em> und damit wird der \u00fcbergebene Zeiger an <em>LoadBitmap<\/em> ung\u00fcltig, mit der Folge, dass die \u00fcrspr\u00fcngliche Bitmap nicht mehr gefunden wird, wenn in der\u00a0Zwischenzeit der Heap auf dem dieser String lag neu verwendet wurde. In der Release Version trat dieser Fehler selten auf. In der Debug Version war der Fehler sofort nachvollziehbar, denn hier wird der Heap bei der Freigabe auf einen einhaltlichen Wert zur\u00fcckgesetzt.<\/p>\n<p>Die L\u00f6sung ist einfach: Es ist n\u00f6tig den alten Inhalt zu kopieren um einen g\u00fcltigen Zeiger zu behalten.<\/p>\n<pre lang=\"cpp\">void CImageButton::OnSysColorChange()\r\n{\r\n  \/\/ System colors changed\r\n  CButton::OnSysColorChange();\r\n  \/\/ We need to protect the resource name, because LoadItem calls\r\n  \/\/ Clear and this might empty m_sResource. And this causes\r\n  \/\/ the string object on the stack to get deleted and the pointer\r\n  \/\/ points into nowhere land. So we use a copy of the string here.\r\n  CString strRessource(m_strResource);\r\n  LoadBitmap(strRessource.IsEmpty() ? m_lpszResource : strRessource);\r\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Wieder mal ein Beispiel f\u00fcr einen versteckten Bug. Nachfolgender Code sieht ganz unscheinbar aus, aber er birgt eine Falle mit sich, die in der Implementierung der Klasse verborgen ist: void CImageButton::OnSysColorChange() { \/\/ Farbe hat ge\u00e4ndert CButton::OnSysColorChange(); \/\/ Bitmap neu laden LoadBitmap(m_strResource.IsEmpty() ? m_lpszResource : m_strResource); } LoadBitmap ist eine Funktion, die die Bitmap neu &hellip; <a href=\"http:\/\/blog.m-ri.de\/index.php\/2011\/12\/05\/die-tucke-mit-temporaren-objekten-und-konvertierungs-operatoren\/\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eDie T\u00fccke mit tempor\u00e4ren Objekten und Konvertierungs-Operatoren\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":[30,3],"tags":[370,136],"class_list":["post-596","post","type-post","status-publish","format-standard","hentry","category-c","category-programmieren","tag-c","tag-qualitaetssicherung"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/596","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=596"}],"version-history":[{"count":0,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/596\/revisions"}],"wp:attachment":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/media?parent=596"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/categories?post=596"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/tags?post=596"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}