{"id":5703,"date":"2012-12-28T07:00:00","date_gmt":"2012-12-28T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2012\/12\/28\/what-do-heaplock-and-heapunlock-do-and-when-do-i-need-to-call-them\/"},"modified":"2012-12-28T07:00:00","modified_gmt":"2012-12-28T07:00:00","slug":"what-do-heaplock-and-heapunlock-do-and-when-do-i-need-to-call-them","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20121228-00\/?p=5703","title":{"rendered":"What do HeapLock and HeapUnlock do, and when do I need to call them?"},"content":{"rendered":"<p>\nYou never need to call the <code>Heap&shy;Lock<\/code> and\n<code>Heap&shy;Unlock<\/code> functions under normal operation.\nAssuming the heap is serialized\n(which is the default),\nall the standard heap functions like\n<code>Heap&shy;Allocate<\/code> and <code>Heap&shy;Free<\/code>\nwill automatically serialize.\n<\/p>\n<p>\nIn fact, the way they serialize is by calling\nthe&sup1; <code>Heap&shy;Lock<\/code> and\n<code>Heap&shy;Unlock<\/code> functions!\n<\/p>\n<p>\nNearly all heap operations complete in a single call.\nIf your heap is serialized, this means that the heap operation\ntakes the heap lock,\ndoes its work,\nand then releases the heap lock and returns.\nIf <i>all<\/i> heap operations were like this,\nthen there would be no need for\n<code>Heap&shy;Lock<\/code> or\n<code>Heap&shy;Unlock<\/code>.\n<\/p>\n<p>\nUnfortunately, there is also the\n<code>Heap&shy;Walk<\/code> function,\nwhich does a little bit of work, and then returns\nwith a partial result.\nThe design for <code>Heap&shy;Walk<\/code> is that\nthe application calls the function repeatedly\nuntil it either gets all the results it wants, or gets bored and gives up.\nBut wait, what if the heap changes while the application is\ntrying to walk through it?\nTo prevent that from happening,\nthe program can call\n<code>Heap&shy;Lock<\/code> before starting the enumeration,\nand\n<code>Heap&shy;Unlock<\/code> when it is done.\nDuring the time the heap is locked,\nother threads which attempt to call a\n<code>Heap&shy;Xxx<\/code> function with that same heap\nwill block until the heap is unlocked.\n<\/p>\n<p>\nThe ability to lock the heap creates a lot of potential for craziness,\nbecause the heap is a high-traffic area.\nAs a result, it is very important that any code which calls\n<code>Heap&shy;Lock<\/code> do very little while the lock is held.\nTake the lock, do your thing, and get out quickly.\n<\/p>\n<p>\nBut wait, there&#8217;s more.\nHolding the heap lock blocks all other threads from\nallocating or freeing memory.\nThis puts the heap lock very low in your lock hierarchy.\nTherefore,\nwhile you hold the heap lock,\nyou cannot block on synchronization objects whose owners might\ntry to access the heap you just locked.\nConsider the following:\n<\/p>\n<pre>\n<i>\/\/ Code in italics is wrong.\nvoid BadIdea()\n{\n HeapLock(GetProcessHeap());\n SendMessage(...);\n HeapUnlock(GetProcessHeap());\n}<\/i>\n<\/pre>\n<p>\nSending a message is a big deal.\nThe thread that is the target of the message\nmay be waiting for the heap lock,\nand now you&#8217;ve created a deadlock.\nYou won&#8217;t proceed until that thread processes the message,\nbut that thread can&#8217;t process the message until you unlock the heap.\n<\/p>\n<p>\nYou might accidentally do something wrong while hold the heap lock\nif you happen to trigger a delay-loaded DLL,\nin which case your call into that other DLL turns into a call\nto <code>Load&shy;Library<\/code>, and now you&#8217;ve lost control.\nIn practice,\nthe only thing you should be doing while holding the heap lock\nis calling <code>Heap&shy;Walk<\/code> and saving the results\nlocally, and in a way that doesn&#8217;t allocate or free memory\non the heap you are walking!\nWait until after you unlock the heap to\nstart studying the results you\ncollected or transfer the raw data into a more suitable data structure.\n<\/p>\n<p>\n<b>Bonus chatter<\/b>\n<\/p>\n<p>\nNote that if you call\n<code>Heap&shy;Lock<\/code> or <code>Heap&shy;Unlock<\/code>\non a heap that was created without serialization\n(<code>HEAP_NO_SERIALIZATION<\/code>),\nthen the results are undefined.\nThat&#8217;s because passing the\n<code>HEAP_NO_SERIALIZATION<\/code> flag means\n&#8220;Hey, Heap Manager,\ndon&#8217;t bother locking this heap.\nI will take responsibility for ensuring that only one thread\noperates on this heap at a time.&#8221;\nIf you later call\n<code>Heap&shy;Lock<\/code> on a no-serialization heap,\nthe heap manager will say,\n&#8220;Wha?\nYou said that <i>you<\/i> would take care of serialization, not me!&#8221;\n<\/p>\n<p>\nIt&#8217;s like ordering a car and saying,\n&#8220;Don&#8217;t bother installing door locks.\nI will take responsibility for ensuring the safety of the car.\n(Say, by never letting the car leave a secured facility.)&#8221;\nAnd then a month later, calling OnStar and saying,\n&#8220;Hi, can you remotely lock my car for me? Thanks.&#8221;\nDude, you explicitly opted out of door locks.\n<\/p>\n<p>\n(Amazingly, I encountered one developer who thought that\ncalling <code>Heap&shy;Lock<\/code> on a no-serialization heap\nwould cause other heap operations on the heap to be blocked,\neven if they passed the\n<code>HEAP_NO_SERIALIZATION<\/code> flag to those operations.\nUm, no, the <code>Heap&shy;Lock<\/code> function cannot lock a\nno-serialization heap because a no-serialization heap <i>doesn&#8217;t have\nlock in the first place, at your request<\/i>.)\n<\/p>\n<p>\n<b>Nitpicker&#8217;s corner<\/b>\n<\/p>\n<p>\n&sup1; s\/the\/the functional equivalents of\/<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You never need to call the Heap&shy;Lock and Heap&shy;Unlock functions under normal operation. Assuming the heap is serialized (which is the default), all the standard heap functions like Heap&shy;Allocate and Heap&shy;Free will automatically serialize. In fact, the way they serialize is by calling the&sup1; Heap&shy;Lock and Heap&shy;Unlock functions! Nearly all heap operations complete in a [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-5703","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>You never need to call the Heap&shy;Lock and Heap&shy;Unlock functions under normal operation. Assuming the heap is serialized (which is the default), all the standard heap functions like Heap&shy;Allocate and Heap&shy;Free will automatically serialize. In fact, the way they serialize is by calling the&sup1; Heap&shy;Lock and Heap&shy;Unlock functions! Nearly all heap operations complete in a [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/5703","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=5703"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/5703\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=5703"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=5703"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=5703"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}