{"id":288,"date":"2008-08-26T22:03:58","date_gmt":"2008-08-26T22:03:58","guid":{"rendered":"http:\/\/kera.name\/articles\/?p=288"},"modified":"2010-08-11T14:03:24","modified_gmt":"2010-08-11T14:03:24","slug":"tomalaks-tuesday-tip","status":"publish","type":"post","link":"https:\/\/kera.name\/articles\/2008\/08\/tomalaks-tuesday-tip\/","title":{"rendered":"Tomalak&#039;s Tuesday Tip"},"content":{"rendered":"<p>I might write a tip every week: I certainly seem to make enough mistakes to come up with them with such frequency.<\/p>\n<p>Today I quickly point out a possible bug that can easily come about in C++ if you&#039;re altering interfaces. I had an stdlib vector of items that was being passed in from another class by reference that was then passed to a function:<\/p>\n<p><textarea name=\"code\" class=\"cpp:nocontrols:nogutter\" cols=\"60\" rows=\"10\">std::vector<double>& items = DataSrc->getItems();<\/p>\n<p>\/\/ using: int f(const std::vector<double>& items);\nint calculationResult = f(items);<\/textarea>\n<\/p>\n<p>When I came to making my code more efficient, I noticed that the internals of f() would be better suited to work with an array of doubles, rather than an stdlib vector. (To be precise I was passing vertex data to OpenGL for rendering, but I&#039;ve greatly simplified the story for this post.)<\/p>\n<p>Taking advantage of the contiguous storage afforded by stdlib vectors I simply passed a pointer to the first element, thus bypassing the auxiliary members of std::vector and effectively providing a simple array reference:<\/p>\n<p><textarea name=\"code\" class=\"cpp:nocontrols:nogutter\" cols=\"60\" rows=\"10\">const std::vector<double>& items = DataSrc->getItems();<\/p>\n<p>\/\/ using: int g(const double* items);\nint calculationResult = g(&items[0]);<\/textarea>\n<\/p>\n<p>So far so good.<\/p>\n<p>Eventually I altered the structure of DataSource (and this is why interfaces should be frozen before implementation, people!) to always pass around pointers where necessary, to help avoid accidental data duplication. I figured that my compiler would help me update all my references to <code>items<\/code> so I didn&#039;t spend too much time tracking down all affected lines.<\/p>\n<p>The result was this:<\/p>\n<p><textarea name=\"code\" class=\"cpp:nocontrols:nogutter\" cols=\"60\" rows=\"10\">const std::vector<double>* items = DataSrc->getItems();\nint calculationResult = g(&items[0]);<\/textarea>\n<\/p>\n<p>My expectations fell apart the moment I realised that relying wholly on compiler error messages is a Bad Idea. In fact, the above code is not an error; it merely isn&#039;t what I meant. Instead of giving me a pointer to the first element in the vector, it gave me the address of the pointer to the vector, which wasn&#039;t entirely useful. This side effect of C++&#039;s implicit array-access-to-pointers had me chasing a segmentation fault in OpenGL for three days.<\/p>\n<p>The corrected code reads thus:<\/p>\n<p><textarea name=\"code\" class=\"cpp:nocontrols:nogutter\" cols=\"60\" rows=\"10\">const std::vector<double><em> items = DataSrc->getItems();\nint calculationResult = g(&(<\/em>items)[0]);<\/textarea>\n<\/p>\n<p>And that could probably be done a whole lot nicer; but it compiles, runs and functions without mangling my machine&#039;s memory.<\/p>\n<p>The moral of today&#039;s story is that if you really, <em>really<\/em> must alter an interface during or even after implementation, do not rely on your compiler to help you find change points: search for them yourself with a fine tooth comb. Or, ideally, just get your interface right the first time. That&#039;s what I&#039;ll be doing from now on.<\/p>\n<p><b>Updated 11\/08\/2010:<\/b> Left-aligned asterisks\/ampersands in types, and replaced &#034;STL&#034; with &#034;stdlib&#034;. I&#039;ve learned a few things in two years.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today I quickly point out a possible bug that can easily come about in C++ if you&#039;re altering interfaces.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[21,20,33],"_links":{"self":[{"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/posts\/288"}],"collection":[{"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/comments?post=288"}],"version-history":[{"count":5,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/posts\/288\/revisions"}],"predecessor-version":[{"id":520,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/posts\/288\/revisions\/520"}],"wp:attachment":[{"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/media?parent=288"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/categories?post=288"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/tags?post=288"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}