<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:wfw="http://wellformedweb.org/CommentAPI/"
     >
  <channel>
    <title>mojavy.com</title>
    <link>http://mojavy.com/blog</link>
    <description></description>
    <pubDate>Wed, 05 Mar 2014 21:25:23 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>malloc+memsetとcallocの違いについて</title>
      <link>http://mojavy.com/blog/2014/03/05/difference-between-malloc-and-calloc/</link>
      <pubDate>Wed, 05 Mar 2014 21:25:23 JST</pubDate>
      <category><![CDATA[os]]></category>
      <category><![CDATA[programming]]></category>
      <guid isPermaLink="true">http://mojavy.com/blog/2014/03/05/difference-between-malloc-and-calloc/</guid>
      <description>malloc+memsetとcallocの違いについて</description>
      <content:encoded><![CDATA[<p><code>malloc</code>と<code>calloc</code>の違いは、表面的には引数の数と<code>calloc</code>は確保した領域を0で初期化するという点くらいですが、以下のコードを大きな<code>n</code>で実行すると、今時のOSだと<code>malloc</code> + <code>memset</code>のほうが大幅に遅くなる可能性があります。</p>
<div class="pygments_borland"><pre><span class="kt">void</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">malloc</span><span class="p">(</span><span class="n">n</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">type</span><span class="p">));</span>
<span class="n">memset</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">n</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">type</span><span class="p">));</span>
</pre></div>

<div class="pygments_borland"><pre><span class="kt">void</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">calloc</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">type</span><span class="p">));</span>
</pre></div>

<p>カーネルはセキュリティ上の理由からメモリを0で初期化してからユーザプロセスに渡します。</p>
<p>しかし、仮想メモリをサポートしたシステムでは、実際にそのメモリに書き込みが発生するまでカーネルはread onlyな領域を複数プロセスで共有させることができるため、既に初期化してあるページであればこの処理を省略できる場合があります。</p>
<p><code>brk</code>で拡張した領域は0で初期化されているので、<code>calloc</code>は新規確保した領域は初期化を省略することができ、結果的に<code>calloc</code>を実行したタイミングでは初期化が実際にはほとんど発生しない、ということがありえます。</p>
<p>一方<code>memset</code>の場合は実際にメモリへの書込みが発生する上、ページの共有もできなくなるためswapする可能性もあります。</p>
<p><br>
<br></p>
<p>ちなみに、(カーネルではなく)<code>calloc</code>自身が0初期化する処理と、<code>memset</code>の処理は微妙に違います。
なぜなら、<code>memset</code>は対象の領域がアラインされているかどうかについての情報なしに処理する必要があるので、境界部分は1byteずつやるしかありません。</p>
<p>じゃあ<code>memset</code>のほうが遅いのかというと、コンパイラによってはアラインされていることを推測できる場合もあったり、callocはライブラリ関数なので移植性のために最適化しにくかったりするので、結局のところ微妙です。</p>
<p>参考： <a href="http://stackoverflow.com/questions/2688466/why-mallocmemset-is-slower-than-calloc">http://stackoverflow.com/questions/2688466/why-mallocmemset-is-slower-than-calloc</a> </p>]]></content:encoded>
    </item>
  </channel>
</rss>
