<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: 编写一个DLL时应当注意什么#1</title>
	<atom:link href="http://www.windameister.org/blog/2009/09/06/what-should-you-think-about-when-writting-a-dl/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.windameister.org/blog/2009/09/06/what-should-you-think-about-when-writting-a-dl/</link>
	<description>learn, think, share, communication</description>
	<lastBuildDate>Sat, 26 Nov 2011 03:23:20 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
	<item>
		<title>By: windam</title>
		<link>http://www.windameister.org/blog/2009/09/06/what-should-you-think-about-when-writting-a-dl/comment-page-1/#comment-481</link>
		<dc:creator>windam</dc:creator>
		<pubDate>Sun, 03 Apr 2011 11:26:57 +0000</pubDate>
		<guid isPermaLink="false">http://www.windameister.org/blog/?p=106#comment-481</guid>
		<description>&lt;blockquote&gt;
&lt;a href=&quot;#comment-480&quot; rel=&quot;nofollow&quot;&gt;
&lt;strong&gt;&lt;em&gt;coldfall:&lt;/em&gt;&lt;/strong&gt;
&lt;/a&gt;
 &lt;p&gt;对应的，如果你使用DLL，由于DLL中会自行初始化一份CRT堆，因此它的内存申请与释放是在有别于在EXE的CRT堆中进行的（两个不同的CRT堆），如果你从DLL中申请一块内存出来使用，最后也必须交还给DLL模块内部去释放。否则会产生Heap Collision，在Debug模式下，你会收到一个系统位于malloc中的断言，并了解到发生了什么。&lt;br&gt;
=============================&lt;br&gt;
对这一段话持不同意见，DLL中使用malloc或者new申请的堆内存是由其加载的MSVCRT.dll或其他的C/C++运行库DLL来分配和管理的，因此如果整个虚拟空间中只有一份该DLL映射，对于堆的管理是不会有问题的。出现你上面提到的问题，多半是因为EXE和DLL使用了不同版本的MSVCRT.dll等运行库DLL，因此EXE运行时是由运行时库DLL1来管理堆，而DLL是由运行时库DLL2来管理堆，也就会发生了上面的问题，因为DLL1中的堆中并没有DLL2中分配的堆内存，各自有各自的CRT堆，各管各的。&lt;/p&gt;
&lt;/blockquote&gt;

非常感谢您的质疑。 :)
针对该情况，我编写了一个测试程序进行验证，发现确实是我此前对这个问题产生了误解。

情景如下：
在Dll中导出一个函数
char* allocMem(int size)
{
return (char*) malloc(size);
}

并在EXE中直接free该函数返回的指针。

分两种情况：
1. 如果EXE与DLL使用的是同一个的msvcrt，不仅仅是版本，则不会出现问题。（/Md, /Mt）
2. 如果EXE与DLL使用的是不同的msvcrt，则会引发我所提到的堆内存错误。（此前我误解为每个Dll会有一个自己的堆，事实上应是每一个crt有一个自己的堆）

这里所说的“同一个”，特指两个2进制模块都链接的是动态crt。如果其中有一个使用的是静态CRT就不行。

究其原因，是由于CRT采用全局变量_crtheap维护了一个Heap的句柄，因此如果所有二进制模块都通过动态链接的方式使用同一个CRT，就不会引发问题。

然而，如果有某个模块链接了一份静态CRT，由于被静态链接到二进制文件中的全局变量会独立存在，因此会使得同一个进程存在使用了两个或更多的crt堆的情况。</description>
		<content:encoded><![CDATA[<blockquote><p>
<a href="#comment-480" rel="nofollow"><br />
<strong><em>coldfall:</em></strong><br />
</a></p>
<p>对应的，如果你使用DLL，由于DLL中会自行初始化一份CRT堆，因此它的内存申请与释放是在有别于在EXE的CRT堆中进行的（两个不同的CRT堆），如果你从DLL中申请一块内存出来使用，最后也必须交还给DLL模块内部去释放。否则会产生Heap Collision，在Debug模式下，你会收到一个系统位于malloc中的断言，并了解到发生了什么。<br />
=============================<br />
对这一段话持不同意见，DLL中使用malloc或者new申请的堆内存是由其加载的MSVCRT.dll或其他的C/C++运行库DLL来分配和管理的，因此如果整个虚拟空间中只有一份该DLL映射，对于堆的管理是不会有问题的。出现你上面提到的问题，多半是因为EXE和DLL使用了不同版本的MSVCRT.dll等运行库DLL，因此EXE运行时是由运行时库DLL1来管理堆，而DLL是由运行时库DLL2来管理堆，也就会发生了上面的问题，因为DLL1中的堆中并没有DLL2中分配的堆内存，各自有各自的CRT堆，各管各的。</p>
</blockquote>
<p>非常感谢您的质疑。 <img src='http://www.windameister.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
针对该情况，我编写了一个测试程序进行验证，发现确实是我此前对这个问题产生了误解。</p>
<p>情景如下：<br />
在Dll中导出一个函数<br />
char* allocMem(int size)<br />
{<br />
return (char*) malloc(size);<br />
}</p>
<p>并在EXE中直接free该函数返回的指针。</p>
<p>分两种情况：<br />
1. 如果EXE与DLL使用的是同一个的msvcrt，不仅仅是版本，则不会出现问题。（/Md, /Mt）<br />
2. 如果EXE与DLL使用的是不同的msvcrt，则会引发我所提到的堆内存错误。（此前我误解为每个Dll会有一个自己的堆，事实上应是每一个crt有一个自己的堆）</p>
<p>这里所说的“同一个”，特指两个2进制模块都链接的是动态crt。如果其中有一个使用的是静态CRT就不行。</p>
<p>究其原因，是由于CRT采用全局变量_crtheap维护了一个Heap的句柄，因此如果所有二进制模块都通过动态链接的方式使用同一个CRT，就不会引发问题。</p>
<p>然而，如果有某个模块链接了一份静态CRT，由于被静态链接到二进制文件中的全局变量会独立存在，因此会使得同一个进程存在使用了两个或更多的crt堆的情况。</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: coldfall</title>
		<link>http://www.windameister.org/blog/2009/09/06/what-should-you-think-about-when-writting-a-dl/comment-page-1/#comment-480</link>
		<dc:creator>coldfall</dc:creator>
		<pubDate>Sat, 02 Apr 2011 03:09:36 +0000</pubDate>
		<guid isPermaLink="false">http://www.windameister.org/blog/?p=106#comment-480</guid>
		<description>对应的，如果你使用DLL，由于DLL中会自行初始化一份CRT堆，因此它的内存申请与释放是在有别于在EXE的CRT堆中进行的（两个不同的CRT堆），如果你从DLL中申请一块内存出来使用，最后也必须交还给DLL模块内部去释放。否则会产生Heap Collision，在Debug模式下，你会收到一个系统位于malloc中的断言，并了解到发生了什么。
=============================
对这一段话持不同意见，DLL中使用malloc或者new申请的堆内存是由其加载的MSVCRT.dll或其他的C/C++运行库DLL来分配和管理的，因此如果整个虚拟空间中只有一份该DLL映射，对于堆的管理是不会有问题的。出现你上面提到的问题，多半是因为EXE和DLL使用了不同版本的MSVCRT.dll等运行库DLL，因此EXE运行时是由运行时库DLL1来管理堆，而DLL是由运行时库DLL2来管理堆，也就会发生了上面的问题，因为DLL1中的堆中并没有DLL2中分配的堆内存，各自有各自的CRT堆，各管各的。</description>
		<content:encoded><![CDATA[<p>对应的，如果你使用DLL，由于DLL中会自行初始化一份CRT堆，因此它的内存申请与释放是在有别于在EXE的CRT堆中进行的（两个不同的CRT堆），如果你从DLL中申请一块内存出来使用，最后也必须交还给DLL模块内部去释放。否则会产生Heap Collision，在Debug模式下，你会收到一个系统位于malloc中的断言，并了解到发生了什么。<br />
=============================<br />
对这一段话持不同意见，DLL中使用malloc或者new申请的堆内存是由其加载的MSVCRT.dll或其他的C/C++运行库DLL来分配和管理的，因此如果整个虚拟空间中只有一份该DLL映射，对于堆的管理是不会有问题的。出现你上面提到的问题，多半是因为EXE和DLL使用了不同版本的MSVCRT.dll等运行库DLL，因此EXE运行时是由运行时库DLL1来管理堆，而DLL是由运行时库DLL2来管理堆，也就会发生了上面的问题，因为DLL1中的堆中并没有DLL2中分配的堆内存，各自有各自的CRT堆，各管各的。</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: windam</title>
		<link>http://www.windameister.org/blog/2009/09/06/what-should-you-think-about-when-writting-a-dl/comment-page-1/#comment-16</link>
		<dc:creator>windam</dc:creator>
		<pubDate>Tue, 01 Dec 2009 00:55:11 +0000</pubDate>
		<guid isPermaLink="false">http://www.windameister.org/blog/?p=106#comment-16</guid>
		<description>&lt;blockquote&gt;
&lt;a href=&quot;#comment-15&quot; rel=&quot;nofollow&quot;&gt;
&lt;strong&gt;&lt;em&gt;semicircle21:&lt;/em&gt;&lt;/strong&gt;
&lt;/a&gt;
 1. 我觉得 3.a里: 只提供一系列普通函数就很方便,就好像ws2_32.lib那样…你说的“只提供一系列普通函数以及一个实现类的指针”是啥意思?
2. 现在你只关注win32了? linux的lib/so一点都没涉及阿,其实linux动态库的东西也很有意思。
&lt;/blockquote&gt;
1.pImpl 惯用法，之前我也没搞太清楚 = = 这篇文章有些地方会再改改。
2.实际两者的动态链接本质上没什么大差别。</description>
		<content:encoded><![CDATA[<blockquote><p>
<a href="#comment-15" rel="nofollow"><br />
<strong><em>semicircle21:</em></strong><br />
</a><br />
 1. 我觉得 3.a里: 只提供一系列普通函数就很方便,就好像ws2_32.lib那样…你说的“只提供一系列普通函数以及一个实现类的指针”是啥意思?<br />
2. 现在你只关注win32了? linux的lib/so一点都没涉及阿,其实linux动态库的东西也很有意思。
</p></blockquote>
<p>1.pImpl 惯用法，之前我也没搞太清楚 = = 这篇文章有些地方会再改改。<br />
2.实际两者的动态链接本质上没什么大差别。</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: semicircle21</title>
		<link>http://www.windameister.org/blog/2009/09/06/what-should-you-think-about-when-writting-a-dl/comment-page-1/#comment-15</link>
		<dc:creator>semicircle21</dc:creator>
		<pubDate>Sun, 29 Nov 2009 15:30:40 +0000</pubDate>
		<guid isPermaLink="false">http://www.windameister.org/blog/?p=106#comment-15</guid>
		<description>1. 我觉得 3.a里: 只提供一系列普通函数就很方便,就好像ws2_32.lib那样...你说的“只提供一系列普通函数以及一个实现类的指针”是啥意思?

2. 现在你只关注win32了? linux的lib/so一点都没涉及阿,其实linux动态库的东西也很有意思。</description>
		<content:encoded><![CDATA[<p>1. 我觉得 3.a里: 只提供一系列普通函数就很方便,就好像ws2_32.lib那样&#8230;你说的“只提供一系列普通函数以及一个实现类的指针”是啥意思?</p>
<p>2. 现在你只关注win32了? linux的lib/so一点都没涉及阿,其实linux动态库的东西也很有意思。</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: windam</title>
		<link>http://www.windameister.org/blog/2009/09/06/what-should-you-think-about-when-writting-a-dl/comment-page-1/#comment-10</link>
		<dc:creator>windam</dc:creator>
		<pubDate>Tue, 08 Sep 2009 16:33:06 +0000</pubDate>
		<guid isPermaLink="false">http://www.windameister.org/blog/?p=106#comment-10</guid>
		<description>&lt;a href=&quot;#comment-9&quot; rel=&quot;nofollow&quot;&gt;@Cool&lt;/a&gt;
Cool？ 你的个人网站很nb…… = =</description>
		<content:encoded><![CDATA[<p><a href="#comment-9" rel="nofollow">@Cool</a><br />
Cool？ 你的个人网站很nb…… = =</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Cool</title>
		<link>http://www.windameister.org/blog/2009/09/06/what-should-you-think-about-when-writting-a-dl/comment-page-1/#comment-9</link>
		<dc:creator>Cool</dc:creator>
		<pubDate>Tue, 08 Sep 2009 03:40:07 +0000</pubDate>
		<guid isPermaLink="false">http://www.windameister.org/blog/?p=106#comment-9</guid>
		<description>牛逼


牛逼</description>
		<content:encoded><![CDATA[<p>牛逼</p>
<p>牛逼</p>
]]></content:encoded>
	</item>
</channel>
</rss>

