<div dir="ltr">My concern about this example:<div><br></div><div><span style="font-size:16px">void do_something(foo *p)</span><br style="font-size:16px"><span style="font-size:16px">{</span><br style="font-size:16px"><span style="font-size:16px">    assert(p);</span><br style="font-size:16px"><span style="font-size:16px">    if (p)</span><br style="font-size:16px"><span style="font-size:16px">        p->crash();</span><br style="font-size:16px"><span class="gmail-im" style="font-size:16px">}</span><br></div><div><span class="gmail-im" style="font-size:16px"><br></span></div>Is that by skipping the operation when the pointer is null is that it's not clear what it should do if it's precondition isn't met.  Sure, it won't crash, but it's also not going to "do something."  This can lead to corrupt state and postpones discovery of the bug.<div><br></div><div>If do_something is a public API, then, yes, you have to decide, document, and implement what to do if the caller passes in a null pointer.  If it's an internal API, then the silent elision of the crash merely hides the bug possibly corrupts the debugger's state.  A corrupt debugging state seems (to me) at least as bad as an obvious crash to the user.  Crashes are going to get complained about and investigated.  Silently doing the wrong thing just wastes everyone's time.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Sep 20, 2016 at 1:59 PM, Zachary Turner via lldb-dev <span dir="ltr"><<a href="mailto:lldb-dev@lists.llvm.org" target="_blank">lldb-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><br><div class="gmail_quote"><span class=""><div dir="ltr">On Tue, Sep 20, 2016 at 1:55 PM Greg Clayton <<a href="mailto:gclayton@apple.com" target="_blank">gclayton@apple.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br class="m_-3343498958610301776gmail_msg">
> On Sep 20, 2016, at 1:45 PM, Zachary Turner <<a href="mailto:zturner@google.com" class="m_-3343498958610301776gmail_msg" target="_blank">zturner@google.com</a>> wrote:<br class="m_-3343498958610301776gmail_msg">
><br class="m_-3343498958610301776gmail_msg">
> I do agree that asserts are sometimes used improperly.  But who's to say that the bug was the assert, and not the surrounding code?  For example, consider this code:<br class="m_-3343498958610301776gmail_msg">
><br class="m_-3343498958610301776gmail_msg">
> assert(p);<br class="m_-3343498958610301776gmail_msg">
> int x = *p;<br class="m_-3343498958610301776gmail_msg">
<br class="m_-3343498958610301776gmail_msg">
Should be written as:<br class="m_-3343498958610301776gmail_msg">
<br class="m_-3343498958610301776gmail_msg">
assert(p);<br class="m_-3343498958610301776gmail_msg">
if (!p)<br class="m_-3343498958610301776gmail_msg">
    do_something_correct();<br class="m_-3343498958610301776gmail_msg">
else<br class="m_-3343498958610301776gmail_msg">
    int x = *p;<br class="m_-3343498958610301776gmail_msg">
<br class="m_-3343498958610301776gmail_msg">
><br class="m_-3343498958610301776gmail_msg">
> Should this assert also not be here in library code?  I mean it's obvious that the program is about to crash if p is invalid.  Asserts should mean "you're about to invoke undefined behavior", and a crash is *better* than undefined behavior.  It surfaces the problem so that you can't let it slip under the radar, and it also alerts you to the point that the UB is invoked, rather than later.<br class="m_-3343498958610301776gmail_msg">
><br class="m_-3343498958610301776gmail_msg">
> What about this assert?<br class="m_-3343498958610301776gmail_msg">
><br class="m_-3343498958610301776gmail_msg">
> assert(ptr);<br class="m_-3343498958610301776gmail_msg">
> int x = strlen(ptr);<br class="m_-3343498958610301776gmail_msg">
><br class="m_-3343498958610301776gmail_msg">
> Surely that assert is ok right?  Do we need to check whether ptr is valid EVERY SINGLE TIME we invoke strlen, or any other function for that matter?  The code would be a disastrous mess.<br class="m_-3343498958610301776gmail_msg">
<br class="m_-3343498958610301776gmail_msg">
Again, check before you call if this is in a shared library! What is so hard about that? It is called software that doesn't crash.<br class="m_-3343498958610301776gmail_msg">
<br class="m_-3343498958610301776gmail_msg">
assert(ptr)<br class="m_-3343498958610301776gmail_msg">
int x = ptr ? strlen(ptr) : 0;<br class="m_-3343498958610301776gmail_msg"></blockquote><div><br></div></span><div>I find it hard to believe that you are arguing that you cannot EVER know ANYTHING about the state of your program.  :-/</div><div><br></div><div>This is like arguing that you should run a full heap integrity check every time you perform a memory write, just to be sure you aren't about to crash.  </div><div><br></div><div>If you make a std::vector<>, do we need to verify that its internal pointer is not null before we write to it?   Probably not, right?  Why not?  Because it has a specification of how it works, and it is documented that you can construct one, you can use it.</div><div><br></div><div>It's ok to document how functions work, and it is ok to assume that functions work the way they claim to work.</div></div></div>
<br>______________________________<wbr>_________________<br>
lldb-dev mailing list<br>
<a href="mailto:lldb-dev@lists.llvm.org">lldb-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/lldb-dev</a><br>
<br></blockquote></div><br></div>