{"id":180,"date":"2007-10-16T16:43:54","date_gmt":"2007-10-16T20:43:54","guid":{"rendered":"http:\/\/benjamin.smedbergs.us\/blog\/2007-10-16\/using-dehydra-to-detect-problematic-code\/"},"modified":"2007-10-22T12:49:43","modified_gmt":"2007-10-22T16:49:43","slug":"using-dehydra-to-detect-problematic-code","status":"publish","type":"post","link":"http:\/\/benjamin.smedbergs.us\/blog\/2007-10-16\/using-dehydra-to-detect-problematic-code\/","title":{"rendered":"Using Dehydra to Detect Problematic Code"},"content":{"rendered":"<p>In XPCOMGC, the behavior of <code>nsCOMPtr<\/code> is very different than currently:<\/p>\n<ul>\n<li><code>nsCOMPtr<\/code> should only be used as a class member, never on the stack. Taras is working on a rewriting script that will replace <code>nsCOMPtr&lt;nsIFoo&gt;<\/code> on the stack with a raw <code>nsIFoo*<\/code> (more on that later).\n<li>the purpose of <code>nsCOMPtr<\/code> is not to ensure correct reference counting (there is no reference-counting!); instead it serves to enforce write barriers, so that MMgc can properly perform incremental GC.\n<\/ul>\n<p>I was able to rewrite nsCOMPtr so that existing code code mostly use the existing API: there is however one major difference: <code>getter_AddRefs<\/code> cannot return a pointer directly to the <code>nsCOMPtr<\/code> instance. Instead, it must save the value in a local variable and call <code>nsCOMPtr.set()<\/code> to preserve the write-barrier semantics. It does this using a temporary class:<\/p>\n<pre>\/**\r\n * nsGetterAddRefs is used for XPCOM out parameters that need to be assigned\r\n * to nsCOMPtr members. We can't pass the address of nsCOMPtr.mRawPtr directly\r\n * because of the need to set the write barrier.\r\n *\/\r\ntemplate &lt;class T&gt;\r\nclass nsGetterAddRefs\r\n{\r\npublic:\r\n  explicit\r\n  nsGetterAddRefs(nsCOMPtr&lt;T&gt; &aSmartPtr) :\r\n    mTempPtr(aSmartPtr),\r\n    mTargetSmartPtr(aSmartPtr)\r\n  {\r\n    \/\/ nothing else to do\r\n  }\r\n\r\n  ~nsGetterAddRefs()\r\n  {\r\n    mTargetSmartPtr = mTempPtr;\r\n  }\r\n\r\n  operator T**()\r\n  {\r\n    return &mTempPtr;\r\n  }\r\n\r\nprivate:\r\n  T* mTempPtr;\r\n  nsCOMPtr&lt;T&gt; &mTargetSmartPtr;\r\n};\r\n\r\ntemplate &lt;class T&gt;\r\ninline\r\nnsGetterAddRefs&lt;T&gt;\r\ngetter_AddRefs(nsCOMPtr&lt;T&gt; &aSmartPtr)\r\n{\r\n  return nsGetterAddRefs&lt;T&gt;(aSmartPtr);\r\n}<\/pre>\n<p>For the vast majority of cases where code makes a simple getter call, this works fine:<\/p>\n<pre>nsresult rv = something->GetAFoo(getter_AddRefs(mFoo));<\/pre>\n<p>However, if you test or use the returned value after you get it in the same statement, the value won&#8217;t be assigned yet:<\/p>\n<p><em style=\"color: red\">Bad:<\/em><\/p>\n<pre>if (NS_SUCCEEDED(something->GetAFoo(getter_AddRefs(mFoo))) <em style=\"color: red\">&& mFoo<\/em>)<\/pre>\n<p><em style=\"color: red\">Also bad:<\/em><\/p>\n<pre>NS_SUCCEEDED(something->GetAFoo(getter_AddRefs(mFoo))) <em style=\"color: red\">&& mFoo->DoSomething()<\/em>;<\/pre>\n<p>In the XPCOMGC world, both of these cases will fail because the ~nsGetterAddRefs destructor runs <strong>after<\/strong> the dereference of mFoo. Once we remove stack comptrs, this is not a common occurrence, but it does happen occasionally.<\/p>\n<p>Checking for this kind of pattern is the perfect job for dehydra: <a href='http:\/\/benjamin.smedbergs.us\/blog\/wp-content\/uploads\/2007\/10\/getter-testcase.js' title='getter-testcase.js'>check it out<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In XPCOMGC, the behavior of nsCOMPtr is very different than currently: nsCOMPtr should only be used as a class member, never on the stack. Taras is working on a rewriting script that will replace nsCOMPtr&lt;nsIFoo&gt; on the stack with a raw nsIFoo* (more on that later). the purpose of nsCOMPtr is not to ensure correct [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[57,56,38],"class_list":["post-180","post","type-post","status-publish","format-standard","hentry","category-mozilla","tag-dehydra","tag-mozilla2","tag-xpcom"],"_links":{"self":[{"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/posts\/180","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/comments?post=180"}],"version-history":[{"count":0,"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/posts\/180\/revisions"}],"wp:attachment":[{"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/media?parent=180"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/categories?post=180"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/benjamin.smedbergs.us\/blog\/wp-json\/wp\/v2\/tags?post=180"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}