title: How to ensure local variables are not removed during optimization
body: <p><strong>Background</strong></p>
  
  <p>At work I often end up doing postmorten debugging using core dumps of optimized code.</p>
  
  <p>For certain kinds of difficult non-reproducible failures I would like to have extra information available to me. Adding additional traces is not feasible in these cases as the vast majority of calls are successful and would add millions of "unnecessary" traces per minute which will roll the log files quickly. Catching and tracing is not always feasible as well as some errors might corrupt the environment causing traces to fail.</p>
  
  <p>As our core dumps include the callstack memory I thought I could use an area on the callstack memory for "tracing".</p>
  
  <p><strong>The problem</strong></p>
  
  <p>Thanks to optimizing compilers code like this don't work</p>
  
  <pre><code>void process (int i)
  {
     int save_me = i;
     // Do something else
  }
  </code></pre>
  
  <p>The idea is to store the input variable on the stack by assigning to a local variable. This often works fine in debug mode but in optimized builds the compiler deems the statement to have no side-effects and removes it.</p>
  
  <p><a href="http://man7.org/linux/man-pages/man3/alloca.3.html" rel="nofollow"><code>alloca</code></a> seems like it could work except we target some platforms that don't support <code>alloca</code> and I am unsure how well it plays together with C++.</p>
  
  <p>I experimented a bit and the following code seems to be able to make state "stick" on the stack even in optimized builds:</p>
  
  <pre><code>#include &lt;cstdint&gt;
  #include &lt;stdexcept&gt;
  #include &lt;istream&gt;
  #include &lt;sstream&gt;
  
  struct saved_state
  {
    saved_state ()
      : head  (0xAABBCCDD)
      , tail  (0xEEFF0000)
    {
      std::fill (state, state + 16, 0);
    }
  
    void push (std::int32_t input) volatile
    {
      for (auto i = 15U; i &gt; 0U; --i)
      {
        state[i] = state[i - 1];
      }
      state[0] = input;
    }
  
    volatile std::uint32_t  head      ;
    volatile std::int32_t   state [16];
    volatile std::uint32_t  tail      ;
  };
  
  void invoke (std::int32_t i)
  {
    if (i &gt; 10)
    {
      throw std::runtime_error ("Busted");
    }
  }
  
  void process (std::istream &amp; input)
  {
    saved_state volatile ss;
  
    while (!input.eof ())
    {
      std::int32_t i;
      if (input &gt;&gt; i)
      {
        ss.push (i);
        invoke (i);
      }
    }
  }
  
  int main()
  {
    std::istringstream input ("1\n2\n30\n");
    process (input);
    return 0;
  }
  </code></pre>
  
  <p><strong>The question</strong></p>
  
  <p>Can I expect the code to do what I want it to do? It seems to work in for our current set of compilers (clang &amp; gcc) but can I expect it to continue to work?</p>
  
  <p>Is there a better way to achieve what I want to do?</p>
  
  <p>By better I mean simpler, more robust or standard conforming.</p>