<div dir="ltr">I found the root cause, but I don't know what's the best approach to fix it.<div><br></div><div>Under windows, 64 bit, when a function is created the void *User::operator new(size_t Size) operator allocates space + Use*.</div><div>In the Use* the HasHungOffUses is set to true. So the ptr to the use* is returned as new object. This ptr is NOT the ptr that was allocated by the system. For that ptr you need ptr - word length. It's important that we use free on the original ptr.</div><div><br></div><div>The void User::operator delete(void *Usr) deletes the use* when dtor is called. However, tracing through the Function() ctor I see that the </div><div>HasHungOffUses is set to False (!).  And when we arrive at the User::delete, the HasHungOffUses has the wrong value causing it to flow into the else part.</div><div><br></div><div><div>void User::operator delete(void *Usr) {</div><div>  // Hung off uses use a single Use* before the User, while other subclasses</div><div>  // use a Use[] allocated prior to the user.</div><div>  User *Obj = static_cast<User *>(Usr);</div><div>  if (Obj->HasHungOffUses) {</div><div>    assert(!Obj->HasDescriptor && "not supported!");</div><div><br></div><div>    Use **HungOffOperandList = static_cast<Use **>(Usr) - 1;</div><div>    // drop the hung off uses.</div><div>    Use::zap(*HungOffOperandList, *HungOffOperandList + Obj->NumUserOperands,</div><div>             /* Delete */ true);</div><div>    ::operator delete(HungOffOperandList);</div><div>  } else if (Obj->HasDescriptor) {</div><div>    Use *UseBegin = static_cast<Use *>(Usr) - Obj->NumUserOperands;</div><div>    Use::zap(UseBegin, UseBegin + Obj->NumUserOperands, /* Delete */ false);</div><div><br></div><div>    auto *DI = reinterpret_cast<DescriptorInfo *>(UseBegin) - 1;</div><div>    uint8_t *Storage = reinterpret_cast<uint8_t *>(DI) - DI->SizeInBytes;</div><div>    ::operator delete(Storage);</div><div>  } else {</div><div>    Use *Storage = static_cast<Use *>(Usr) - Obj->NumUserOperands;</div><div>    Use::zap(Storage, Storage + Obj->NumUserOperands,</div><div>             /* Delete */ false);</div><div>    ::operator delete(Storage);</div><div>  }</div><div>}</div></div><div><br></div><div>The storage address is computed wrongly in this case, it's off by 1 word length. And so visual studio sees that I'm not freeing the org allocated ptr and throws heap error. During debug when I force HasHungOffUses = true, everything is fine and the correct original ptr is computed and freed. So I'm guessing that that value should have stayed true.</div><div><br></div><div>I also have set a data breakpoint on HashHungOffUses when it's accessed and did noticed that </div><div><div> <span class="" style="white-space:pre"> </span>ConsoleEngine.exe!llvm::Function::__autoclassinit2(unsigned __int64)<span class="" style="white-space:pre">      </span>C++</div><div><span class="" style="white-space:pre">        </span>ConsoleEngine.exe!llvm::Function::Create(llvm::FunctionType * Ty, llvm::GlobalValue::LinkageTypes Linkage, const llvm::Twine & N, llvm::Module * M) Line 116<span class="" style="white-space:pre">  </span>C++</div><div> </div></div><div>caused it to be set to False. So do I need to trace into all the Function bases classes and find out where it is set to false? or do I need to fix the Storage address computation in the else part?</div><div><br></div><div>Cheers,</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Feb 25, 2016 at 1:07 PM, koffie drinker <span dir="ltr"><<a href="mailto:gekkekoe@gmail.com" target="_blank">gekkekoe@gmail.com</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">I made the llvm::Function() constructor public (for testing purpose) and used the non-overloaded new.<div><br></div><div>auto func = ::new llvm::Function(...)<br></div><div><span style="font-size:12.8px">if (func) func->eraseFromParent();</span><br></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">And the heap corruption is gone! Did something changed in llvm::User::new between 3.7.1 and 3.8.0 ?</span></div><div><span style="font-size:12.8px">I found a bug in llvm ?</span></div><div><span style="font-size:12.8px"><br></span></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Feb 25, 2016 at 12:10 PM, koffie drinker <span dir="ltr"><<a href="mailto:gekkekoe@gmail.com" target="_blank">gekkekoe@gmail.com</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">I downloaded 3.8.0rc3 and I also have it in 3.8.0rc3.<div>I did set a data access breakpoint on the first function ptr that causes the invalid heap. This would allow me to break whenever someone is touching that address. It did not show double deletes during debugging. Further more I managed to narrow it down to 2 function calls:</div><div><br></div><div>// stupid code, but its just for triggering heap error</div><div>auto func = llvm::Function::Create(...);</div><div>if (func) func->eraseFromParent();</div><div><br></div><div>The erase from parent triggers the invalid heap. I used appverif.exe and gflags.exe (page heap checks) but they could not find anything.</div><div>The Function::Create is just a wrapper for new Function(). I also traced into this call, but did not see anything weird. It returns a valid ptr.</div><div>Somehow the ptr returned by the new seems to be broken. If i'm not mistaken the new operator is overloaded by llvm? I could not try to use the default new Function() since its constructor is not accessible from outside.</div><div><br></div><div>I'm kinda lost where to look next. There's not much that could go wrong with creating a function and deleting it? </div><div>I'm using visual studio 2015 update1, and could not find any known issue regarding heaps. I'm at a point where I'm suspecting my compiler.</div><div>But its weird that the same compiler works fine with 3.7.1</div><div><br></div><div>any ideas would be appreciated</div><div><br></div></div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Feb 24, 2016 at 9:10 AM, koffie drinker <span dir="ltr"><<a href="mailto:gekkekoe@gmail.com" target="_blank">gekkekoe@gmail.com</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"><div><br></div><div>I recently upgraded from llvm 3.7.1 to a pre release of llvm (3.8.0rc2) in order to test some issues regarding bug 24233.</div><div>After upgrading I starting to see heap corruption messages in vs 2015 sp1 when my program exits. </div><div>"HEAP[ConsoleEngine.exe]: Invalid address specified to RtlValidateHeap( 0000000000290000, 0000000000318698 )" </div><div><br></div><div>Initially I only got it in Release build. Debug build seems to be fine, but recently I also got them in Debug build.</div><div>I traced it down how to trigger it in Debug Mode. It happens when I put the ExecutionEngine creation in the constructor in the cpp file.</div><div>If I put it in the h file then there's no problem. This leads me to believe that it is probably not my code that is causing it since I never seem to have</div><div>this issue in the past (3.6.x - 3.7.x). I've include the stack traces below this email.</div><div><br></div><div>It fails when the dtor is called for the first module. MCJIT only has 2 modules, the first one only has function declarations. The second one is empty. No codegen is taking place.</div><div><br></div><div>I googled for the error message and it seems to be happen when you delete a resource twice. </div><div>Did something change for 3.8.0 regarding to function decl. creation in a module? Any tips on how to trace it down further? I can't seem to make a small example demonstration the problem. It only seems to be triggered in a larger project (again: nearly code works fine in 3.6.x-3.7.x)</div><div><br></div><div><br></div><div>-- Release mode stack trace</div><div> <span style="white-space:pre-wrap">    </span>ntdll.dll!RtlReportCriticalFailure()<span style="white-space:pre-wrap">    </span>Unknown</div><div> <span style="white-space:pre-wrap">        </span>ntdll.dll!RtlpReportHeapFailure()<span style="white-space:pre-wrap">       </span>Unknown</div><div> <span style="white-space:pre-wrap">        </span>ntdll.dll!RtlpHeapHandleError()<span style="white-space:pre-wrap"> </span>Unknown</div><div> <span style="white-space:pre-wrap">        </span>ntdll.dll!RtlpLogHeapFailure()<span style="white-space:pre-wrap">  </span>Unknown</div><div> <span style="white-space:pre-wrap">        </span>ntdll.dll!string "Enabling heap debug options\n"()<span style="white-space:pre-wrap">    </span>Unknown</div><div> <span style="white-space:pre-wrap">        </span>ucrtbase.dll!free()<span style="white-space:pre-wrap">     </span>Unknown</div><div> <span style="white-space:pre-wrap">        </span>ConsoleEngine.exe!llvm::Function::`vector deleting destructor'(unsigned int)<span style="white-space:pre-wrap">        </span>C++</div><div> <span style="white-space:pre-wrap">    </span>ConsoleEngine.exe!llvm::Module::~Module(void)<span style="white-space:pre-wrap">   </span>C++</div><div> <span style="white-space:pre-wrap">    </span>ConsoleEngine.exe!llvm::MCJIT::OwningModuleContainer::freeModulePtrSet(class llvm::SmallPtrSet<class llvm::Module *,4> &)<span style="white-space:pre-wrap">     </span>C++</div><div> <span style="white-space:pre-wrap">    </span>ConsoleEngine.exe!llvm::MCJIT::~MCJIT(void)<span style="white-space:pre-wrap">     </span>C++</div><div> <span style="white-space:pre-wrap">    </span>ConsoleEngine.exe!llvm::MCJIT::`vector deleting destructor'(unsigned int)<span style="white-space:pre-wrap">   </span>C++</div><div><br></div><div><span style="white-space:pre-wrap">     </span></div><div>-- Debug Mode stack trace</div><div><span style="white-space:pre-wrap"> </span>ntdll.dll!RtlpBreakPointHeap()<span style="white-space:pre-wrap">  </span>Unknown</div><div> <span style="white-space:pre-wrap">        </span>ntdll.dll!string "Enabling heap debug options\n"()<span style="white-space:pre-wrap">    </span>Unknown</div><div> <span style="white-space:pre-wrap">        </span>ntdll.dll!RtlValidateHeap()<span style="white-space:pre-wrap">     </span>Unknown</div><div> <span style="white-space:pre-wrap">        </span>KernelBase.dll!HeapValidate()<span style="white-space:pre-wrap">   </span>Unknown</div><div> <span style="white-space:pre-wrap">        </span>ucrtbased.dll!_CrtIsValidHeapPointer()<span style="white-space:pre-wrap">  </span>Unknown</div><div> <span style="white-space:pre-wrap">        </span>ucrtbased.dll!_calloc_base()<span style="white-space:pre-wrap">    </span>Unknown</div><div> <span style="white-space:pre-wrap">        </span>ucrtbased.dll!_free_dbg()<span style="white-space:pre-wrap">       </span>Unknown</div><div> <span style="white-space:pre-wrap">        </span>ConsoleEngine.exe!operator delete(void * block) Line 21<span style="white-space:pre-wrap"> </span>C++</div><div><span style="white-space:pre-wrap">      </span>ConsoleEngine.exe!llvm::User::operator delete(void * Usr) Line 195<span style="white-space:pre-wrap">      </span>C++</div><div> <span style="white-space:pre-wrap">    </span>ConsoleEngine.exe!llvm::Function::`scalar deleting destructor'(unsigned int)<span style="white-space:pre-wrap">        </span>C++</div><div> <span style="white-space:pre-wrap">    </span>ConsoleEngine.exe!llvm::ilist_node_traits<llvm::Function>::deleteNode(llvm::Function * V) Line 160<span style="white-space:pre-wrap">        </span>C++</div><div> <span style="white-space:pre-wrap">    </span>ConsoleEngine.exe!llvm::iplist<llvm::Function,llvm::SymbolTableListTraits<llvm::Function> >::erase(llvm::ilist_iterator<llvm::Function> where) Line 519<span style="white-space:pre-wrap">       </span>C++</div><div> <span style="white-space:pre-wrap">    </span>ConsoleEngine.exe!llvm::iplist<llvm::Function,llvm::SymbolTableListTraits<llvm::Function> >::erase(llvm::ilist_iterator<llvm::Function> first, llvm::ilist_iterator<llvm::Function> last) Line 601<span style="white-space:pre-wrap">      </span>C++</div><div> <span style="white-space:pre-wrap">    </span>ConsoleEngine.exe!llvm::iplist<llvm::Function,llvm::SymbolTableListTraits<llvm::Function> >::clear() Line 605<span style="white-space:pre-wrap">       </span>C++</div><div> <span style="white-space:pre-wrap">    </span>ConsoleEngine.exe!llvm::Module::~Module() Line 61<span style="white-space:pre-wrap">       </span>C++</div><div> <span style="white-space:pre-wrap">    </span>ConsoleEngine.exe!llvm::Module::`scalar deleting destructor'(unsigned int)<span style="white-space:pre-wrap">  </span>C++</div><div> <span style="white-space:pre-wrap">    </span>ConsoleEngine.exe!llvm::MCJIT::OwningModuleContainer::freeModulePtrSet(llvm::SmallPtrSet<llvm::Module *,4> & MPS) Line 175<span style="white-space:pre-wrap">    </span>C++</div><div> <span style="white-space:pre-wrap">    </span>ConsoleEngine.exe!llvm::MCJIT::OwningModuleContainer::~OwningModuleContainer() Line 82<span style="white-space:pre-wrap">  </span>C++</div><div> <span style="white-space:pre-wrap">    </span>ConsoleEngine.exe!llvm::MCJIT::~MCJIT() Line 102<span style="white-space:pre-wrap">        </span>C++</div><div> <span style="white-space:pre-wrap">    </span>ConsoleEngine.exe!llvm::MCJIT::`scalar deleting destructor'(unsigned int)<span style="white-space:pre-wrap">   </span>C++</div><div> <span style="white-space:pre-wrap">    </span>ConsoleEngine.exe!std::default_delete<llvm::ExecutionEngine>::operator()(llvm::ExecutionEngine * _Ptr) Line 1195<span style="white-space:pre-wrap">  </span>C++</div><div> <span style="white-space:pre-wrap">    </span>ConsoleEngine.exe!std::unique_ptr<llvm::ExecutionEngine,std::default_delete<llvm::ExecutionEngine> >::~unique_ptr<llvm::ExecutionEngine,std::default_delete<llvm::ExecutionEngine> >() Line 1398<span style="white-space:pre-wrap">        </span>C++</div><div><br></div></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br></div>