<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Ptrdiff_t is evil</title><link>http://blogs.msdn.com/b/david_leblanc/archive/2008/09/02/ptrdiff-t-is-evil.aspx</link><description>Well, not really, but here's a code problem that confounded some really smart devs – and it looks so simple! 
 void IncPtr( unsigned int cElements ) 
 { 
 if( m_pMax - m_pCurrent &amp;gt; cElements ) 
 m_pCurrent += cElements; 
 else 
 throw; 
 } </description><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><item><title>re: Ptrdiff_t is evil</title><link>http://blogs.msdn.com/b/david_leblanc/archive/2008/09/02/ptrdiff-t-is-evil.aspx#10047238</link><pubDate>Fri, 06 Aug 2010 23:37:23 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10047238</guid><dc:creator>gvisser</dc:creator><description>&lt;p&gt;A better comparison is to test the sum vs the max:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;if ( (m_pCurrent + cElements) &amp;gt; m_pMax ) throw;&lt;/p&gt;
&lt;p&gt;[dcl] Except that any pointer addition outside of the buffer isn&amp;#39;t defined by the standard, and could be optimized out, which is exactly what gcc did a while back. Regardless of what the compiler does, we shouldn&amp;#39;t write non-standard code.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Your issue with&lt;/p&gt;
&lt;p&gt;&amp;nbsp;If ( ptrdiff_t &amp;lt; unsigned int )&lt;/p&gt;
&lt;p&gt;becoming&lt;/p&gt;
&lt;p&gt;&amp;nbsp;If (__int64 &amp;lt; unsigned int )&lt;/p&gt;
&lt;p&gt;is the result of Microsoft&amp;#39;s decision to use the LLP64 Data Model, not because ptrdiff_t is evil.&lt;/p&gt;
&lt;p&gt;[dcl] That&amp;#39;s incorrect. It&amp;#39;s the result of the C standard and how operator casts work.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10047238" width="1" height="1"&gt;</description></item><item><title>re: Ptrdiff_t is evil</title><link>http://blogs.msdn.com/b/david_leblanc/archive/2008/09/02/ptrdiff-t-is-evil.aspx#10038995</link><pubDate>Fri, 16 Jul 2010 06:53:34 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10038995</guid><dc:creator>aaron</dc:creator><description>&lt;p&gt;Which is why ptrdiff_t and size_t should always go hand in hand. &amp;nbsp;The error is that cElements should be of type size_t.&lt;/p&gt;
&lt;p&gt;[dcl] That and overloading the bounds check for the pointer difference to rule out negative value by using a &amp;#39;clever&amp;#39; side-effect.&lt;/p&gt;
&lt;p&gt;Also, I thought that, technically, it&amp;#39;s possible for sizeof(ptrdiff_t) != sizeof(void*), but rather you&amp;#39;re only guaranteed that sizeof(intptr_t) == sizeof(void*). &amp;nbsp;In practice, though, you&amp;#39;ll probably get by with either.&lt;/p&gt;
&lt;p&gt;[dcl] I think you&amp;#39;re right, but as you point out, in practice they&amp;#39;re the same.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10038995" width="1" height="1"&gt;</description></item><item><title>re: Ptrdiff_t is evil</title><link>http://blogs.msdn.com/b/david_leblanc/archive/2008/09/02/ptrdiff-t-is-evil.aspx#9804469</link><pubDate>Fri, 26 Jun 2009 02:22:25 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9804469</guid><dc:creator>david_leblanc</dc:creator><description>&lt;p&gt;Someone wrote me, and pointed out:&lt;/p&gt;
&lt;p&gt;You give the following example:&lt;/p&gt;
&lt;p&gt;void IncPtr( unsigned int cElements )&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;if( m_pMax - m_pCurrent &amp;lt; cElements )&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;m_pCurrent += cElements;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;else&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;throw;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;The logic of this conditional statement seems messed up. &amp;nbsp;Suppose the variables have been initialized like this:&lt;/p&gt;
&lt;p&gt;static int array[10];&lt;/p&gt;
&lt;p&gt;m_pCurrent = array + 5;&lt;/p&gt;
&lt;p&gt;m_pMax = array + 10;&lt;/p&gt;
&lt;p&gt;i.e. m_pMax points to the end of the array and m_pCurrent points somewhere in the middle. &amp;nbsp;From the names, I expect this is how the variables would be used.&lt;/p&gt;
&lt;p&gt;Then, something calls IncPtr(2). &amp;nbsp;Now, m_pMax - m_pCurrent is 5, and 5 &amp;lt; 2 is false, so the function throws (assuming it's called from a catch clause) as if there had been an error. &amp;nbsp;However, it would have been perfectly safe to increment m_pCurrent by 2. &lt;/p&gt;
&lt;p&gt;On the other hand, if something calls IncPtr(99), then 5 &amp;lt; 99 is true, and the function happily does m_pCurrent += cElements, incrementing the pointer far past the end of the array.&lt;/p&gt;
&lt;p&gt;Thus, the test should be inverted. &amp;nbsp;And if you do that, then the behaviour in 64-bit builds, where the unsigned int gets converted to ptrdiff_t without any compiler warnings, will actually become correct; and the 32-bit builds that trigger a warning will exhibit the bug.&lt;/p&gt;
&lt;p&gt;[dcl] This has now been fixed. The overall point that the branch is different depending on build is the important bit.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9804469" width="1" height="1"&gt;</description></item><item><title>re: Ptrdiff_t is evil</title><link>http://blogs.msdn.com/b/david_leblanc/archive/2008/09/02/ptrdiff-t-is-evil.aspx#9532439</link><pubDate>Sun, 05 Apr 2009 23:57:52 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9532439</guid><dc:creator>Shane Hatagawa</dc:creator><description>&lt;P&gt;Is taking _either_ branch of this function a good thing? &amp;nbsp;You imply that having the function throw is 'safe', but the class is not in a valid state, right? &amp;nbsp;Any attempt to use the class is already going to access an out of bounds element, changing m_pCurrent from one invalid value to another isn't going to help, but throwing from this function isn't going to help either. &amp;nbsp;Ideally this class would be checking invariants, and would have caught this when the error occurred. &amp;nbsp;As for the secure choice in this circumstance? &amp;nbsp;I don't see how you could do anything safe here except terminate (if possible saving as much user state for a better restart/recover). &amp;nbsp;None of this takes away from your discussion here, but sometimes in the face of broken program state, there is no safe alternative except to just stop the train.&lt;/P&gt;
&lt;P&gt;[dcl] good points, but it is just an example, and what's the right error path is very dependent on a lot of context we don't have. The main point is that give the same input, we go down different branches on 32 and 64-bit, which is a really nasty trick.&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9532439" width="1" height="1"&gt;</description></item><item><title>a-foton &amp;raquo; Ptrdiff_t is evil</title><link>http://blogs.msdn.com/b/david_leblanc/archive/2008/09/02/ptrdiff-t-is-evil.aspx#8920940</link><pubDate>Wed, 03 Sep 2008 02:20:26 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8920940</guid><dc:creator>a-foton &amp;raquo; Ptrdiff_t is evil</dc:creator><description>&lt;p&gt;PingBack from &lt;a rel="nofollow" target="_new" href="http://blog.a-foton.ru/2008/09/ptrdiff_t-is-evil/"&gt;http://blog.a-foton.ru/2008/09/ptrdiff_t-is-evil/&lt;/a&gt;&lt;/p&gt;
&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8920940" width="1" height="1"&gt;</description></item></channel></rss>