{"id":1027,"date":"2019-10-23T21:15:42","date_gmt":"2019-10-24T02:15:42","guid":{"rendered":"http:\/\/sunapi386.ca\/wordpress\/?p=1027"},"modified":"2019-10-23T21:15:50","modified_gmt":"2019-10-24T02:15:50","slug":"c-what-is-copy_elision-and-why-you-should-know-about-it","status":"publish","type":"post","link":"https:\/\/sunapi386.ca\/wordpress\/c-what-is-copy_elision-and-why-you-should-know-about-it\/","title":{"rendered":"[C++] What is copy_elision and why you should know about it"},"content":{"rendered":"\n<p>In the C++ world, <strong>copy_elision<\/strong> is a compiler optimization. <\/p>\n\n\n\n<p>Prior to C++11, there was no copy_elision, so when you write code like this&#8230;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Person makePerson() {\n    Person p();\n    p.name = \"Bob\";\n    return p;\n}<\/code><\/pre>\n\n\n\n<p>&#8230; the compiler creates a Person object in the makePerson stack frame and is copied\/moved to the caller&#8217;s stack after makePerson finshes.<\/p>\n\n\n\n<p>But with with copy_elision, the compiler optimizes the process and rather than a move\/copy, compiler sets the address of makePerson&#8217;s Person directly to the return address. In other words, there is no move\/copy. <\/p>\n\n\n\n<p>Explained by the official website <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/copy_elision\">https:\/\/en.cppreference.com\/w\/cpp\/language\/copy_elision<\/a><\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>The objects are constructed directly into the storage where they would otherwise be copied\/moved to.<\/p><\/blockquote>\n\n\n\n<p>This optimization is usually unnoticed.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Great! So what? Why do I need to care about this?<\/h2>\n\n\n\n<p>Tl;dr: When you lie to the compiler. <\/p>\n\n\n\n<p>As a general rule: if you lie to the compiler, there lies bugs, undefined behavior, and probably stack smashing.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Let me tell a story about using <a href=\"http:\/\/wiki.ros.org\/\">ROS<\/a>. <\/h2>\n\n\n\n<p>ROS creates a layer of abstraction for inter process communication (IPC) with sockets, in a publisher\/subscriber model.<\/p>\n\n\n\n<p>The ROS semantics for a subscriber is very overloaded, as in there are many definitions of &#8220;subscribe&#8221;.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1552\" height=\"958\" src=\"https:\/\/i1.wp.com\/sunapi386.ca\/wordpress\/wp-content\/uploads\/2019\/10\/image-4.png?fit=625%2C386\" alt=\"\" class=\"wp-image-1028\" srcset=\"https:\/\/sunapi386.ca\/wordpress\/wp-content\/uploads\/2019\/10\/image-4.png 1552w, https:\/\/sunapi386.ca\/wordpress\/wp-content\/uploads\/2019\/10\/image-4-300x185.png 300w, https:\/\/sunapi386.ca\/wordpress\/wp-content\/uploads\/2019\/10\/image-4-768x474.png 768w, https:\/\/sunapi386.ca\/wordpress\/wp-content\/uploads\/2019\/10\/image-4-1024x632.png 1024w, https:\/\/sunapi386.ca\/wordpress\/wp-content\/uploads\/2019\/10\/image-4-624x385.png 624w\" sizes=\"auto, (max-width: 1552px) 100vw, 1552px\" \/><\/figure>\n\n\n\n<p><a href=\"http:\/\/docs.ros.org\/lunar\/api\/roscpp\/html\/classros_1_1NodeHandle.html\">http:\/\/docs.ros.org\/lunar\/api\/roscpp\/html\/classros_1_1NodeHandle.html<\/a><\/p>\n\n\n\n<p>Here&#8217;s what happened.<\/p>\n\n\n\n<p>I defined an Object and created a callback. E.g. Cards object and callback_add_card(Card newCard). <\/p>\n\n\n\n<p>I<strong>mportant<\/strong>: <strong>The callback returned an int. E.g. &#8220;int callback_add_card&#8221;.<\/strong><br><strong>This leads me to make a mistake&#8230; We shall see why later.<\/strong><\/p>\n\n\n\n<p>I constructed the object and passed that object&#8217;s callback to ROS subscribe. <\/p>\n\n\n\n<p>But ROS&#8217;s subscribe definition expected (void*) function pointer. <br><strong>I.e. void callback_add_card was acceptable but int callback_add_card is not. <\/strong><br>So I lied to the compiler and cast this to a void*. Subtle mistake. Won&#8217;t show up until later.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#define callback_add_card_fn (<strong>void <\/strong>(Cards::*)(<strong>const <\/strong>Card&amp;))\n\nnodeHandle.subscribe(\"\/cards\/add\", subscribeQueueSize, callback_add_card_fn &amp;Cards::callback_add_card, &amp;my_cards);<\/pre>\n\n\n\n<p>The compiler was happy and compiled. Because the &#8220;#define cb_car_speed &#8230;&#8221; told the compiler to treat the function as void.<\/p>\n\n\n\n<p><strong>Code mostly worked fine.<\/strong><\/p>\n\n\n\n<p>Because an int is relatively small (byte), there appears to be no bugs because the stack smashing wasn&#8217;t obvious.<\/p>\n\n\n\n<p>Sometime later, I changed the return type.<br>From int callback_add_card to Card callback_add_card.<br>Because why not just return the Card instead? So I can write some test code and see if the Card is correct.<\/p>\n\n\n\n<p>Well! Now we have big trouble.<\/p>\n\n\n\n<p>The compiler was told this callback_add_card had void return type. So compiler did not allocate any space for a return value. And because of copy_elison, the compiler had generated code for callback_add_card &#8220;<em>directly into the storage where they would otherwise be copied\/moved to.<\/em>&#8221; <\/p>\n\n\n\n<p><strong>In other words, calling <\/strong>callback_add_card<strong> smashes the stack of the caller. Because the caller expected void  return value, and no spaces was allocated. <\/strong><span style=\"text-decoration: underline;\"><strong>But the copy_elison code constructed the Card object in the caller&#8217;s stack frame!<\/strong><\/span><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">So how do we get around this? How to have a callback that returns some value, but still call the ROS subscribe properly?<\/h2>\n\n\n\n<p>Answer: By wrapping the call in a lambda, creating a closure. The lambda returns no value, so it&#8217;s a void function. But the lambda can capture context. E.g.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">nodeHandle.subscribe&lt;Card>(\"\/cards\/add\", subscribeQueueSize, [&amp;my_cards](Card newCard) {\n  cout &lt;&lt; \"the card added is: \" &lt;&lt; my_cards.callback_add_card() &lt;&lt; \"\\n\";\n});<\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the C++ world, copy_elision is a compiler optimization. Prior to C++11, there was no copy_elision, so when you write code like this&#8230; &#8230; the compiler creates a Person object in the makePerson stack frame and is copied\/moved to the caller&#8217;s stack after makePerson finshes. But with with copy_elision, the compiler optimizes the process and &hellip; <a href=\"https:\/\/sunapi386.ca\/wordpress\/c-what-is-copy_elision-and-why-you-should-know-about-it\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">[C++] What is copy_elision and why you should know about it<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[34],"tags":[],"class_list":["post-1027","post","type-post","status-publish","format-standard","hentry","category-thoughts"],"_links":{"self":[{"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/posts\/1027","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/comments?post=1027"}],"version-history":[{"count":1,"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/posts\/1027\/revisions"}],"predecessor-version":[{"id":1029,"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/posts\/1027\/revisions\/1029"}],"wp:attachment":[{"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/media?parent=1027"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/categories?post=1027"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/tags?post=1027"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}