{"id":1124,"date":"2013-03-21T17:43:26","date_gmt":"2013-03-21T07:43:26","guid":{"rendered":"http:\/\/brnz.org\/hbr\/?p=1124"},"modified":"2013-03-26T15:43:08","modified_gmt":"2013-03-26T05:43:08","slug":"bugs-of-the-day-2013-03-20","status":"publish","type":"post","link":"https:\/\/brnz.org\/hbr\/?p=1124","title":{"rendered":"Bugs of the day, Wednesday 2013-03-20"},"content":{"rendered":"<h2>Uninitialized class member<\/h2>\n<h3>The problem:<\/h3>\n<pre escaped=\"true\" lang=\"cpp\">struct Foo {\r\n\u00a0 int m_A;\r\n\u00a0 int m_B;\r\n\u00a0 int m_C;\r\n\u00a0 Foo():m_A(0), m_B(0) {}\r\n\u00a0 void Bar() {\r\n\u00a0 \u00a0 DoSomethingWith(m_C); \/\/ fail it\r\n\u00a0 }\r\n};<\/pre>\n<p>My defense is that this was spread across a header and a .cpp file, which is to say I was careless. (My preference really is to put all code inline in one place &#8212; .h and .cpp is repetitive and costs time and effort to keep in sync)<\/p>\n<p>This was some existing code that I reworked a couple of weeks ago and hadn&#8217;t got to the point of running\/testing until today. I&#8217;m really not sure how I managed to remove the initializer here &#8212; it existed in the original version.<\/p>\n<h3>The fix:<\/h3>\n<p>Initialize to zero, which was not just known-value, but correct-starting-value.<\/p>\n<h3>Prevention:<\/h3>\n<p>Always initialize everything. Keep class definitions in sync with constructors and Init() methods.<\/p>\n<h2>Sliced inheritance<\/h2>\n<h3>The problem:<\/h3>\n<pre escaped=\"true\" lang=\"cpp\">class Bar {\r\n\u00a0 virtual void Baz() {\/*nothing interesting*\/}\r\n};\r\n\r\nclass BarExtender: public Bar {\r\n\u00a0 virtual void Baz() {DoSomethingInteresting();}\r\n};\r\n\r\nclass Foo : public Bar {\r\n\u00a0 Foo(Bar&amp; bar): Bar(bar) {}\r\n\u00a0 void Yolo() { Baz(); }\r\n};\r\n\r\nBarExtender b;\r\nFoo f(b);\r\nf.Yolo(); \/\/ intended that this would DoSomethingInteresting(). Actually does nothing interesting<\/pre>\n<h3>The fix:<\/h3>\n<pre escaped=\"true\" lang=\"cpp\">class Foo : public Bar {\r\n\u00a0 Foo(Bar&amp; bar): m_Bar(bar) {}\r\n\u00a0 void Yolo() { m_Bar.Baz(); }\r\n\u00a0 Bar&amp; m_Bar;\r\n};<\/pre>\n<h3>Prevention:<\/h3>\n<p>Know the language well enough to know when you&#8217;re writing code that doesn&#8217;t say what you mean.<\/p>\n<h2>Undesired printf output<\/h2>\n<h3>The problem:<\/h3>\n<p>This is the first &#8220;functional&#8221; bug &#8212; something that didn&#8217;t work quite the way I&#8217;d intended.<\/p>\n<p>For a data serialization class, I had hoped to replace several functions of the form:<\/p>\n<pre escaped=\"true\" lang=\"cpp\">WriteInt32(int32_t i) { snprintf(..., \"%d\", i); }\r\nWriteDouble(double d) { snprintf(..., \"%f\", d); }<\/pre>\n<p>to a single function:<\/p>\n<pre escaped=\"true\" lang=\"cpp\">WriteNumber(double d) { snprintf(..., \"%f\", d); \u00a0}<\/pre>\n<p>Unfortunately, the <strong>%f<\/strong> format specifier will, by default, always write a decimal point and 6 figures thereafter, which is undesirable for integers-types-cast-to-double written by this function &#8212; for particular use cases it doubles (hah!) the size of the data written.<\/p>\n<h3>The fix:<\/h3>\n<p>I&#8217;ve not tested this yet, but it looks like <strong>%g<\/strong> (or probably\u00a0<strong>%.<em>n<\/em>g<\/strong> will provide the desired behaviour by not writing the surplus zeroes. I will need to determine if the output for floating point input and large integers will be acceptable.<\/p>\n<h3>Prevention:<\/h3>\n<p>I still have a lot to learn about <strong>printf<\/strong> format specifiers, though I&#8217;ve found\u00a0<a href=\"http:\/\/www.cplusplus.com\/reference\/cstdio\/printf\/\">http:\/\/www.cplusplus.com\/reference\/cstdio\/printf\/<\/a>\u00a0useful when considering\/trying to to understand the available options. This does make me wonder if a printf-format-string constructor exists analogous to <a href=\"http:\/\/cdecl.org\">http:\/\/cdecl.org<\/a> &#8230;<\/p>\n<h3>Update:<\/h3>\n<p>Rather than trying to find a single format that works for all input or testing the number before printing it, I&#8217;ve opted to overload the function by type. This way we can use knowledge of the type to do something appropriate and more efficient.<\/p>\n<p>I have overloads for <strong>int<\/strong>, <strong>unsigned int<\/strong>, <strong>double<\/strong>, <strong>long<\/strong> and <strong>unsigned long<\/strong>, and a comment as to why there&#8217;s no implementation for <strong>unsigned long long<\/strong> (the loader treats all numbers as doubles, which means we could end up writing out numbers that we can&#8217;t read back without loss of precision along the way). I&#8217;ve also added static asserts in case this code gets compiled on a system where sizeof(long) &gt; sizeof(int).\u00a0There are separate functions for writing out\u00a0<strong>bool<\/strong>\u00a0and pointer values.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Uninitialized class member The problem: struct Foo { \u00a0 int m_A; \u00a0 int m_B; \u00a0 int m_C; \u00a0 Foo():m_A(0), m_B(0) {} \u00a0 void Bar() { \u00a0 \u00a0 DoSomethingWith(m_C); \/\/ fail it \u00a0 } }; My defense is that this was spread across a header and a .cpp file, which is to say I was careless. &hellip; <a href=\"https:\/\/brnz.org\/hbr\/?p=1124\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Bugs of the day, Wednesday 2013-03-20&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[26],"tags":[],"_links":{"self":[{"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=\/wp\/v2\/posts\/1124"}],"collection":[{"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1124"}],"version-history":[{"count":11,"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=\/wp\/v2\/posts\/1124\/revisions"}],"predecessor-version":[{"id":1132,"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=\/wp\/v2\/posts\/1124\/revisions\/1132"}],"wp:attachment":[{"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1124"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1124"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1124"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}