766 lines
72 KiB
HTML
766 lines
72 KiB
HTML
|
||
<!DOCTYPE html>
|
||
|
||
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_CN">
|
||
<head>
|
||
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||
|
||
<title>内存管理 — Python 3.8.20 文档</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
||
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
|
||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
||
|
||
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
||
<script src="../_static/jquery.js"></script>
|
||
<script src="../_static/underscore.js"></script>
|
||
<script src="../_static/doctools.js"></script>
|
||
<script src="../_static/language_data.js"></script>
|
||
<script src="../_static/translations.js"></script>
|
||
|
||
<script src="../_static/sidebar.js"></script>
|
||
|
||
<link rel="search" type="application/opensearchdescription+xml"
|
||
title="在 Python 3.8.20 文档 中搜索"
|
||
href="../_static/opensearch.xml"/>
|
||
<link rel="author" title="关于这些文档" href="../about.html" />
|
||
<link rel="index" title="索引" href="../genindex.html" />
|
||
<link rel="search" title="搜索" href="../search.html" />
|
||
<link rel="copyright" title="版权所有" href="../copyright.html" />
|
||
<link rel="next" title="对象实现支持" href="objimpl.html" />
|
||
<link rel="prev" title="Python初始化配置" href="init_config.html" />
|
||
<link rel="canonical" href="https://docs.python.org/3/c-api/memory.html" />
|
||
|
||
|
||
|
||
|
||
|
||
<style>
|
||
@media only screen {
|
||
table.full-width-table {
|
||
width: 100%;
|
||
}
|
||
}
|
||
</style>
|
||
<link rel="shortcut icon" type="image/png" href="../_static/py.svg" />
|
||
<script type="text/javascript" src="../_static/copybutton.js"></script>
|
||
<script type="text/javascript" src="../_static/menu.js"></script>
|
||
|
||
</head>
|
||
<body>
|
||
<div class="mobile-nav">
|
||
<input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
|
||
aria-pressed="false" aria-expanded="false" role="button" aria-label="Menu" />
|
||
<label for="menuToggler" class="toggler__label">
|
||
<span></span>
|
||
</label>
|
||
<nav class="nav-content" role="navigation">
|
||
<a href="https://www.python.org/" class="nav-logo">
|
||
<img src="../_static/py.svg" alt="Logo"/>
|
||
</a>
|
||
<div class="version_switcher_placeholder"></div>
|
||
<form role="search" class="search" action="../search.html" method="get">
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
|
||
<path fill-rule="nonzero"
|
||
d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" fill="#444"></path>
|
||
</svg>
|
||
<input type="text" name="q" aria-label="快速搜索"/>
|
||
<input type="submit" value="转向"/>
|
||
</form>
|
||
</nav>
|
||
<div class="menu-wrapper">
|
||
<nav class="menu" role="navigation" aria-label="main navigation">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<h3><a href="../contents.html">目录</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#">内存管理</a><ul>
|
||
<li><a class="reference internal" href="#overview">概述</a></li>
|
||
<li><a class="reference internal" href="#raw-memory-interface">原始内存接口</a></li>
|
||
<li><a class="reference internal" href="#memory-interface">内存接口</a></li>
|
||
<li><a class="reference internal" href="#object-allocators">对象分配器</a></li>
|
||
<li><a class="reference internal" href="#default-memory-allocators">默认内存分配器</a></li>
|
||
<li><a class="reference internal" href="#customize-memory-allocators">自定义内存分配器</a></li>
|
||
<li><a class="reference internal" href="#the-pymalloc-allocator">pymalloc 分配器</a><ul>
|
||
<li><a class="reference internal" href="#customize-pymalloc-arena-allocator">自定义 pymalloc Arena 分配器</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#tracemalloc-c-api">tracemalloc C API</a></li>
|
||
<li><a class="reference internal" href="#examples">例子</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<h4>上一个主题</h4>
|
||
<p class="topless"><a href="init_config.html"
|
||
title="上一章">Python初始化配置</a></p>
|
||
<h4>下一个主题</h4>
|
||
<p class="topless"><a href="objimpl.html"
|
||
title="下一章">对象实现支持</a></p>
|
||
<div role="note" aria-label="source link">
|
||
<h3>本页</h3>
|
||
<ul class="this-page-menu">
|
||
<li><a href="../bugs.html">报告 Bug</a></li>
|
||
<li>
|
||
<a href="https://github.com/python/cpython/blob/3.8/Doc/c-api/memory.rst"
|
||
rel="nofollow">显示源代码
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="outdated-warning" style="padding: .5em; text-align: center; background-color: #FFBABA; color: #6A0E0E;">
|
||
这个文档所针对的是一个已不再受支持的 Python 旧版本。
|
||
你应当升级版本,并阅读
|
||
<a href="/3/c-api/memory.html"> Python 当前稳定版本的文档</a>.
|
||
</div>
|
||
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<h3>导航</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="../genindex.html" title="总目录"
|
||
accesskey="I">索引</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python 模块索引"
|
||
>模块</a> |</li>
|
||
<li class="right" >
|
||
<a href="objimpl.html" title="对象实现支持"
|
||
accesskey="N">下一页</a> |</li>
|
||
<li class="right" >
|
||
<a href="init_config.html" title="Python初始化配置"
|
||
accesskey="P">上一页</a> |</li>
|
||
|
||
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
|
||
<li><a href="https://www.python.org/">Python</a> »</li>
|
||
<li class="switchers">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<div class="version_switcher_placeholder"></div>
|
||
</li>
|
||
<li>
|
||
|
||
</li>
|
||
<li id="cpython-language-and-version">
|
||
<a href="../index.html">3.8.20 Documentation</a> »
|
||
</li>
|
||
|
||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python/C API 参考手册</a> »</li>
|
||
<li class="right">
|
||
|
||
|
||
<div class="inline-search" role="search">
|
||
<form class="inline-search" action="../search.html" method="get">
|
||
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
|
||
<input type="submit" value="转向" />
|
||
<input type="hidden" name="check_keywords" value="yes" />
|
||
<input type="hidden" name="area" value="default" />
|
||
</form>
|
||
</div>
|
||
|
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="document">
|
||
<div class="documentwrapper">
|
||
<div class="bodywrapper">
|
||
<div class="body" role="main">
|
||
|
||
<section id="memory-management">
|
||
<span id="memory"></span><h1>内存管理<a class="headerlink" href="#memory-management" title="永久链接至标题">¶</a></h1>
|
||
<section id="overview">
|
||
<span id="memoryoverview"></span><h2>概述<a class="headerlink" href="#overview" title="永久链接至标题">¶</a></h2>
|
||
<p>在 Python 中,内存管理涉及到一个包含所有 Python 对象和数据结构的私有堆(heap)。这个私有堆的管理由内部的 <em>Python 内存管理器(Python memory manager)</em> 保证。Python 内存管理器有不同的组件来处理各种动态存储管理方面的问题,如共享、分割、预分配或缓存。</p>
|
||
<p>在最底层,一个原始内存分配器通过与操作系统的内存管理器交互,确保私有堆中有足够的空间来存储所有与 Python 相关的数据。在原始内存分配器的基础上,几个对象特定的分配器在同一堆上运行,并根据每种对象类型的特点实现不同的内存管理策略。例如,整数对象在堆内的管理方式不同于字符串、元组或字典,因为整数需要不同的存储需求和速度与空间的权衡。因此,Python 内存管理器将一些工作分配给对象特定分配器,但确保后者在私有堆的范围内运行。</p>
|
||
<p>Python 堆内存的管理是由解释器来执行,用户对它没有控制权,即使他们经常操作指向堆内内存块的对象指针,理解这一点十分重要。Python 对象和其他内部缓冲区的堆空间分配是由 Python 内存管理器按需通过本文档中列出的 Python/C API 函数进行的。</p>
|
||
<p id="index-0">为了避免内存破坏,扩展的作者永远不应该试图用 C 库函数导出的函数来对 Python 对象进行操作,这些函数包括: <code class="xref c c-func docutils literal notranslate"><span class="pre">malloc()</span></code>, <code class="xref c c-func docutils literal notranslate"><span class="pre">calloc()</span></code>, <code class="xref c c-func docutils literal notranslate"><span class="pre">realloc()</span></code> 和 <code class="xref c c-func docutils literal notranslate"><span class="pre">free()</span></code>。这将导致 C 分配器和 Python 内存管理器之间的混用,引发严重后果,这是由于它们实现了不同的算法,并在不同的堆上操作。但是,我们可以安全地使用 C 库分配器为单独的目的分配和释放内存块,如下例所示:</p>
|
||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">res</span><span class="p">;</span>
|
||
<span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">buf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="p">)</span><span class="w"> </span><span class="n">malloc</span><span class="p">(</span><span class="n">BUFSIZ</span><span class="p">);</span><span class="w"> </span><span class="cm">/* for I/O */</span>
|
||
|
||
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">buf</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span>
|
||
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">PyErr_NoMemory</span><span class="p">();</span>
|
||
<span class="p">...</span><span class="n">Do</span><span class="w"> </span><span class="n">some</span><span class="w"> </span><span class="n">I</span><span class="o">/</span><span class="n">O</span><span class="w"> </span><span class="n">operation</span><span class="w"> </span><span class="n">involving</span><span class="w"> </span><span class="n">buf</span><span class="p">...</span>
|
||
<span class="n">res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyBytes_FromString</span><span class="p">(</span><span class="n">buf</span><span class="p">);</span>
|
||
<span class="n">free</span><span class="p">(</span><span class="n">buf</span><span class="p">);</span><span class="w"> </span><span class="cm">/* malloc'ed */</span>
|
||
<span class="k">return</span><span class="w"> </span><span class="n">res</span><span class="p">;</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>在这个例子中,I/O 缓冲区的内存请求是由 C 库分配器处理的。Python 内存管理器只参与了分配作为结果返回的字节对象。</p>
|
||
<p>然而,在大多数情况下,建议专门从 Python 堆中分配内存,因为后者由 Python 内存管理器控制。例如,当解释器扩展了用 C 写的新对象类型时,就必须这样做。使用 Python 堆的另一个原因是希望*通知* Python 内存管理器关于扩展模块的内存需求。即使所请求的内存全部只用于内部的、高度特定的目的,将所有的内存请求交给 Python 内存管理器能让解释器对其内存占用的整体情况有更准确的了解。因此,在某些情况下,Python 内存管理器可能会触发或不触发适当的操作,如垃圾回收、内存压缩或其他预防性操作。请注意,通过使用前面例子中所示的 C 库分配器,为 I/O 缓冲区分配的内存会完全不受 Python 内存管理器管理。</p>
|
||
<div class="admonition seealso">
|
||
<p class="admonition-title">参见</p>
|
||
<p>环境变量 <span class="target" id="index-9"></span><a class="reference internal" href="../using/cmdline.html#envvar-PYTHONMALLOC"><code class="xref std std-envvar docutils literal notranslate"><span class="pre">PYTHONMALLOC</span></code></a> 可被用来配置 Python 所使用的内存分配器。</p>
|
||
<p>环境变量 <span class="target" id="index-10"></span><a class="reference internal" href="../using/cmdline.html#envvar-PYTHONMALLOCSTATS"><code class="xref std std-envvar docutils literal notranslate"><span class="pre">PYTHONMALLOCSTATS</span></code></a> 可以用来在每次创建和关闭新的 pymalloc 对象区域时打印 <a class="reference internal" href="#pymalloc"><span class="std std-ref">pymalloc 内存分配器</span></a> 的统计数据。</p>
|
||
</div>
|
||
</section>
|
||
<section id="raw-memory-interface">
|
||
<h2>原始内存接口<a class="headerlink" href="#raw-memory-interface" title="永久链接至标题">¶</a></h2>
|
||
<p>以下函数集封装了系统分配器。这些函数是线程安全的,不需要持有 <a class="reference internal" href="../glossary.html#term-global-interpreter-lock"><span class="xref std std-term">全局解释器锁</span></a>。</p>
|
||
<p><a class="reference internal" href="#default-memory-allocators"><span class="std std-ref">default raw memory allocator</span></a> 使用这些函数:<code class="xref c c-func docutils literal notranslate"><span class="pre">malloc()</span></code>、 <code class="xref c c-func docutils literal notranslate"><span class="pre">calloc()</span></code>、 <code class="xref c c-func docutils literal notranslate"><span class="pre">realloc()</span></code> 和 <code class="xref c c-func docutils literal notranslate"><span class="pre">free()</span></code>;申请零字节时则调用 <code class="docutils literal notranslate"><span class="pre">malloc(1)</span></code> (或 <code class="docutils literal notranslate"><span class="pre">calloc(1,</span> <span class="pre">1)</span></code>)</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.4 新版功能.</span></p>
|
||
</div>
|
||
<dl class="function">
|
||
<dt id="c.PyMem_RawMalloc">
|
||
void* <code class="sig-name descname">PyMem_RawMalloc</code><span class="sig-paren">(</span>size_t<em> n</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyMem_RawMalloc" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>分配 <em>n</em> 个字节并返回一个指向分配的内存的 <code class="xref c c-type docutils literal notranslate"><span class="pre">void*</span></code> 类型指针,如果请求失败则返回 <code class="docutils literal notranslate"><span class="pre">NULL</span></code>。</p>
|
||
<p>请求零字节可能返回一个独特的非 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> 指针,就像调用了 <code class="docutils literal notranslate"><span class="pre">PyMem_RawMalloc(1)</span></code> 一样。但是内存不会以任何方式被初始化。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="c.PyMem_RawCalloc">
|
||
void* <code class="sig-name descname">PyMem_RawCalloc</code><span class="sig-paren">(</span>size_t<em> nelem</em>, size_t<em> elsize</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyMem_RawCalloc" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>分配 <em>nelem</em> 个元素,每个元素的大小为 <em>elsize</em> 字节,并返回指向分配的内存的 <code class="xref c c-type docutils literal notranslate"><span class="pre">void*</span></code> 类型指针,如果请求失败则返回 <code class="docutils literal notranslate"><span class="pre">NULL</span></code>。 内存会被初始化为零。</p>
|
||
<p>请求零字节可能返回一个独特的非 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> 指针,就像调用了 <code class="docutils literal notranslate"><span class="pre">PyMem_RawCalloc(1,</span> <span class="pre">1)</span></code> 一样。</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.5 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="c.PyMem_RawRealloc">
|
||
void* <code class="sig-name descname">PyMem_RawRealloc</code><span class="sig-paren">(</span>void<em> *p</em>, size_t<em> n</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyMem_RawRealloc" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>将 <em>p</em> 指向的内存块大小调整为 <em>n</em> 字节。以新旧内存块大小中的最小值为准,其中内容保持不变,</p>
|
||
<p>如果 <em>p</em> 是 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> ,则相当于调用 <code class="docutils literal notranslate"><span class="pre">PyMem_RawMalloc(n)</span></code> ;如果 <em>n</em> 等于 0,则内存块大小会被调整,但不会被释放,返回非 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> 指针。</p>
|
||
<p>除非 <em>p</em> 是 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> ,否则它必须是之前调用 <a class="reference internal" href="#c.PyMem_RawMalloc" title="PyMem_RawMalloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_RawMalloc()</span></code></a> 、 <a class="reference internal" href="#c.PyMem_RawRealloc" title="PyMem_RawRealloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_RawRealloc()</span></code></a> 或 <a class="reference internal" href="#c.PyMem_RawCalloc" title="PyMem_RawCalloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_RawCalloc()</span></code></a> 所返回的。</p>
|
||
<p>如果请求失败,<a class="reference internal" href="#c.PyMem_RawRealloc" title="PyMem_RawRealloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_RawRealloc()</span></code></a> 返回 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> , <em>p</em> 仍然是指向先前内存区域的有效指针。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="c.PyMem_RawFree">
|
||
void <code class="sig-name descname">PyMem_RawFree</code><span class="sig-paren">(</span>void<em> *p</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyMem_RawFree" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>释放 <em>p</em> 指向的内存块。 <em>p</em> 必须是之前调用 <a class="reference internal" href="#c.PyMem_RawMalloc" title="PyMem_RawMalloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_RawMalloc()</span></code></a> 、 <a class="reference internal" href="#c.PyMem_RawRealloc" title="PyMem_RawRealloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_RawRealloc()</span></code></a> 或 <a class="reference internal" href="#c.PyMem_RawCalloc" title="PyMem_RawCalloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_RawCalloc()</span></code></a> 所返回的指针。否则,或在 <code class="docutils literal notranslate"><span class="pre">PyMem_RawFree(p)</span></code> 之前已经调用过的情况下,未定义的行为会发生。</p>
|
||
<p>如果 <em>p</em> 是 <code class="docutils literal notranslate"><span class="pre">NULL</span></code>, 那么什么操作也不会进行。</p>
|
||
</dd></dl>
|
||
|
||
</section>
|
||
<section id="memory-interface">
|
||
<span id="memoryinterface"></span><h2>内存接口<a class="headerlink" href="#memory-interface" title="永久链接至标题">¶</a></h2>
|
||
<p>以下函数集,仿照 ANSI C 标准,并指定了请求零字节时的行为,可用于从Python堆分配和释放内存。</p>
|
||
<p><a class="reference internal" href="#default-memory-allocators"><span class="std std-ref">默认内存分配器</span></a> 使用了 <a class="reference internal" href="#pymalloc"><span class="std std-ref">pymalloc 内存分配器</span></a>.</p>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">警告</p>
|
||
<p>在使用这些函数时,必须持有 <a class="reference internal" href="../glossary.html#term-global-interpreter-lock"><span class="xref std std-term">全局解释器锁(GIL)</span></a> 。</p>
|
||
</div>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.6 版更改: </span>现在默认的分配器是 pymalloc 而非系统的 <code class="xref c c-func docutils literal notranslate"><span class="pre">malloc()</span></code> 。</p>
|
||
</div>
|
||
<dl class="function">
|
||
<dt id="c.PyMem_Malloc">
|
||
void* <code class="sig-name descname">PyMem_Malloc</code><span class="sig-paren">(</span>size_t<em> n</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyMem_Malloc" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>分配 <em>n</em> 个字节并返回一个指向分配的内存的 <code class="xref c c-type docutils literal notranslate"><span class="pre">void*</span></code> 类型指针,如果请求失败则返回 <code class="docutils literal notranslate"><span class="pre">NULL</span></code>。</p>
|
||
<p>请求零字节可能返回一个独特的非 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> 指针,就像调用了 <code class="docutils literal notranslate"><span class="pre">PyMem_Malloc(1)</span></code> 一样。但是内存不会以任何方式被初始化。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="c.PyMem_Calloc">
|
||
void* <code class="sig-name descname">PyMem_Calloc</code><span class="sig-paren">(</span>size_t<em> nelem</em>, size_t<em> elsize</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyMem_Calloc" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>分配 <em>nelem</em> 个元素,每个元素的大小为 <em>elsize</em> 字节,并返回指向分配的内存的 <code class="xref c c-type docutils literal notranslate"><span class="pre">void*</span></code> 类型指针,如果请求失败则返回 <code class="docutils literal notranslate"><span class="pre">NULL</span></code>。 内存会被初始化为零。</p>
|
||
<p>请求零字节可能返回一个独特的非 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> 指针,就像调用了 <code class="docutils literal notranslate"><span class="pre">PyMem_Calloc(1,</span> <span class="pre">1)</span></code> 一样。</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.5 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="c.PyMem_Realloc">
|
||
void* <code class="sig-name descname">PyMem_Realloc</code><span class="sig-paren">(</span>void<em> *p</em>, size_t<em> n</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyMem_Realloc" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>将 <em>p</em> 指向的内存块大小调整为 <em>n</em> 字节。以新旧内存块大小中的最小值为准,其中内容保持不变,</p>
|
||
<p>如果 <em>p</em> 是 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> ,则相当于调用 <code class="docutils literal notranslate"><span class="pre">PyMem_Malloc(n)</span></code> ;如果 <em>n</em> 等于 0,则内存块大小会被调整,但不会被释放,返回非 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> 指针。</p>
|
||
<p>除非 <em>p</em> 是 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> ,否则它必须是之前调用 <a class="reference internal" href="#c.PyMem_Malloc" title="PyMem_Malloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Malloc()</span></code></a> 、 <a class="reference internal" href="#c.PyMem_Realloc" title="PyMem_Realloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Realloc()</span></code></a> 或 <a class="reference internal" href="#c.PyMem_Calloc" title="PyMem_Calloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Calloc()</span></code></a> 所返回的。</p>
|
||
<p>如果请求失败,<a class="reference internal" href="#c.PyMem_Realloc" title="PyMem_Realloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Realloc()</span></code></a> 返回 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> , <em>p</em> 仍然是指向先前内存区域的有效指针。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="c.PyMem_Free">
|
||
void <code class="sig-name descname">PyMem_Free</code><span class="sig-paren">(</span>void<em> *p</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyMem_Free" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>释放 <em>p</em> 指向的内存块。 <em>p</em> 必须是之前调用 <a class="reference internal" href="#c.PyMem_Malloc" title="PyMem_Malloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Malloc()</span></code></a> 、 <a class="reference internal" href="#c.PyMem_Realloc" title="PyMem_Realloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Realloc()</span></code></a> 或 <a class="reference internal" href="#c.PyMem_Calloc" title="PyMem_Calloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Calloc()</span></code></a> 所返回的指针。否则,或在 <code class="docutils literal notranslate"><span class="pre">PyMem_Free(p)</span></code> 之前已经调用过的情况下,未定义的行为会发生。</p>
|
||
<p>如果 <em>p</em> 是 <code class="docutils literal notranslate"><span class="pre">NULL</span></code>, 那么什么操作也不会进行。</p>
|
||
</dd></dl>
|
||
|
||
<p>以下面向类型的宏为方便而提供。 注意 <em>TYPE</em> 可以指任何 C 类型。</p>
|
||
<dl class="function">
|
||
<dt id="c.PyMem_New">
|
||
TYPE* <code class="sig-name descname">PyMem_New</code><span class="sig-paren">(</span>TYPE, size_t<em> n</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyMem_New" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>与 <a class="reference internal" href="#c.PyMem_Malloc" title="PyMem_Malloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Malloc()</span></code></a> 相同,但会分配 <code class="docutils literal notranslate"><span class="pre">(n</span> <span class="pre">*</span> <span class="pre">sizeof(TYPE))</span></code> 字节的内存。 返回一个转换为 <code class="xref c c-type docutils literal notranslate"><span class="pre">TYPE*</span></code> 的指针。 内存将不会以任何方式被初始化。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="c.PyMem_Resize">
|
||
TYPE* <code class="sig-name descname">PyMem_Resize</code><span class="sig-paren">(</span>void<em> *p</em>, TYPE, size_t<em> n</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyMem_Resize" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>与 <a class="reference internal" href="#c.PyMem_Realloc" title="PyMem_Realloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Realloc()</span></code></a> 相同,但内存块的大小被调整为 <code class="docutils literal notranslate"><span class="pre">(n</span> <span class="pre">*</span> <span class="pre">sizeof(TYPE))</span></code> 字节。 返回一个转换为 <code class="xref c c-type docutils literal notranslate"><span class="pre">TYPE*</span></code> 类型的指针。 返回时,<em>p</em> 将为指向新内存区域的指针,如果失败则返回 <code class="docutils literal notranslate"><span class="pre">NULL</span></code>。</p>
|
||
<p>这是一个 C 预处理宏, <em>p</em> 总是被重新赋值。请保存 <em>p</em> 的原始值,以避免在处理错误时丢失内存。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="c.PyMem_Del">
|
||
void <code class="sig-name descname">PyMem_Del</code><span class="sig-paren">(</span>void<em> *p</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyMem_Del" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>与 <a class="reference internal" href="#c.PyMem_Free" title="PyMem_Free"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Free()</span></code></a> 相同</p>
|
||
</dd></dl>
|
||
|
||
<p>此外,我们还提供了以下宏集用于直接调用 Python 内存分配器,而不涉及上面列出的 C API 函数。但是请注意,使用它们并不能保证跨 Python 版本的二进制兼容性,因此在扩展模块被弃用。</p>
|
||
<ul class="simple">
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">PyMem_MALLOC(size)</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">PyMem_NEW(type,</span> <span class="pre">size)</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">PyMem_REALLOC(ptr,</span> <span class="pre">size)</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">PyMem_RESIZE(ptr,</span> <span class="pre">type,</span> <span class="pre">size)</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">PyMem_FREE(ptr)</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">PyMem_DEL(ptr)</span></code></p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="object-allocators">
|
||
<h2>对象分配器<a class="headerlink" href="#object-allocators" title="永久链接至标题">¶</a></h2>
|
||
<p>以下函数集,仿照 ANSI C 标准,并指定了请求零字节时的行为,可用于从Python堆分配和释放内存。</p>
|
||
<p><a class="reference internal" href="#default-memory-allocators"><span class="std std-ref">默认对象分配器</span></a> 使用 <a class="reference internal" href="#pymalloc"><span class="std std-ref">pymalloc 内存分配器</span></a>.</p>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">警告</p>
|
||
<p>在使用这些函数时,必须持有 <a class="reference internal" href="../glossary.html#term-global-interpreter-lock"><span class="xref std std-term">全局解释器锁(GIL)</span></a> 。</p>
|
||
</div>
|
||
<dl class="function">
|
||
<dt id="c.PyObject_Malloc">
|
||
void* <code class="sig-name descname">PyObject_Malloc</code><span class="sig-paren">(</span>size_t<em> n</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyObject_Malloc" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>分配 <em>n</em> 个字节并返回一个指向分配的内存的 <code class="xref c c-type docutils literal notranslate"><span class="pre">void*</span></code> 类型指针,如果请求失败则返回 <code class="docutils literal notranslate"><span class="pre">NULL</span></code>。</p>
|
||
<p>请求零字节可能返回一个独特的非 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> 指针,就像调用了 <code class="docutils literal notranslate"><span class="pre">PyObject_Malloc(1)</span></code> 一样。但是内存不会以任何方式被初始化。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="c.PyObject_Calloc">
|
||
void* <code class="sig-name descname">PyObject_Calloc</code><span class="sig-paren">(</span>size_t<em> nelem</em>, size_t<em> elsize</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyObject_Calloc" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>分配 <em>nelem</em> 个元素,每个元素的大小为 <em>elsize</em> 字节,并返回指向分配的内存的 <code class="xref c c-type docutils literal notranslate"><span class="pre">void*</span></code> 类型指针,如果请求失败则返回 <code class="docutils literal notranslate"><span class="pre">NULL</span></code>。 内存会被初始化为零。</p>
|
||
<p>请求零字节可能返回一个独特的非 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> 指针,就像调用了 <code class="docutils literal notranslate"><span class="pre">PyObject_Calloc(1,</span> <span class="pre">1)</span></code> 一样。</p>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.5 新版功能.</span></p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="c.PyObject_Realloc">
|
||
void* <code class="sig-name descname">PyObject_Realloc</code><span class="sig-paren">(</span>void<em> *p</em>, size_t<em> n</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyObject_Realloc" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>将 <em>p</em> 指向的内存块大小调整为 <em>n</em> 字节。以新旧内存块大小中的最小值为准,其中内容保持不变,</p>
|
||
<p>如果*p*是 <code class="docutils literal notranslate"><span class="pre">NULL</span></code>,则相当于调用 <code class="docutils literal notranslate"><span class="pre">PyObject_Malloc(n)</span></code> ;如果 <em>n</em> 等于 0,则内存块大小会被调整,但不会被释放,返回非 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> 指针。</p>
|
||
<p>除非 <em>p</em> 是 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> ,否则它必须是之前调用 <a class="reference internal" href="#c.PyObject_Malloc" title="PyObject_Malloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Malloc()</span></code></a> 、 <a class="reference internal" href="#c.PyObject_Realloc" title="PyObject_Realloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Realloc()</span></code></a> 或 <a class="reference internal" href="#c.PyObject_Calloc" title="PyObject_Calloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Calloc()</span></code></a> 所返回的。</p>
|
||
<p>如果请求失败,<a class="reference internal" href="#c.PyObject_Realloc" title="PyObject_Realloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Realloc()</span></code></a> 返回 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> , <em>p</em> 仍然是指向先前内存区域的有效指针。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="c.PyObject_Free">
|
||
void <code class="sig-name descname">PyObject_Free</code><span class="sig-paren">(</span>void<em> *p</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyObject_Free" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>释放 <em>p</em> 指向的内存块。 <em>p</em> 必须是之前调用 <a class="reference internal" href="#c.PyObject_Malloc" title="PyObject_Malloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Malloc()</span></code></a> 、 <a class="reference internal" href="#c.PyObject_Realloc" title="PyObject_Realloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Realloc()</span></code></a> 或 <a class="reference internal" href="#c.PyObject_Calloc" title="PyObject_Calloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Calloc()</span></code></a> 所返回的指针。否则,或在 <code class="docutils literal notranslate"><span class="pre">PyObject_Free(p)</span></code> 之前已经调用过的情况下,未定义行为会发生。</p>
|
||
<p>如果 <em>p</em> 是 <code class="docutils literal notranslate"><span class="pre">NULL</span></code>, 那么什么操作也不会进行。</p>
|
||
</dd></dl>
|
||
|
||
</section>
|
||
<section id="default-memory-allocators">
|
||
<span id="id1"></span><h2>默认内存分配器<a class="headerlink" href="#default-memory-allocators" title="永久链接至标题">¶</a></h2>
|
||
<p>默认内存分配器:</p>
|
||
<table class="docutils align-default">
|
||
<colgroup>
|
||
<col style="width: 28%" />
|
||
<col style="width: 18%" />
|
||
<col style="width: 16%" />
|
||
<col style="width: 19%" />
|
||
<col style="width: 18%" />
|
||
</colgroup>
|
||
<thead>
|
||
<tr class="row-odd"><th class="head"><p>配置</p></th>
|
||
<th class="head"><p>名称</p></th>
|
||
<th class="head"><p>PyMem_RawMalloc</p></th>
|
||
<th class="head"><p>PyMem_Malloc</p></th>
|
||
<th class="head"><p>PyObject_Malloc</p></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="row-even"><td><p>发布版本</p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">"pymalloc"</span></code></p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">malloc</span></code></p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">pymalloc</span></code></p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">pymalloc</span></code></p></td>
|
||
</tr>
|
||
<tr class="row-odd"><td><p>调试构建</p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">"pymalloc_debug"</span></code></p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">malloc</span></code> + debug</p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">pymalloc</span></code> + debug</p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">pymalloc</span></code> + debug</p></td>
|
||
</tr>
|
||
<tr class="row-even"><td><p>没有 pymalloc 的发布版本</p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">"malloc"</span></code></p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">malloc</span></code></p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">malloc</span></code></p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">malloc</span></code></p></td>
|
||
</tr>
|
||
<tr class="row-odd"><td><p>没有 pymalloc 的调试构建</p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">"malloc_debug"</span></code></p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">malloc</span></code> + debug</p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">malloc</span></code> + debug</p></td>
|
||
<td><p><code class="docutils literal notranslate"><span class="pre">malloc</span></code> + debug</p></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>说明:</p>
|
||
<ul class="simple">
|
||
<li><p>名称: 环境变量 <span class="target" id="index-11"></span><a class="reference internal" href="../using/cmdline.html#envvar-PYTHONMALLOC"><code class="xref std std-envvar docutils literal notranslate"><span class="pre">PYTHONMALLOC</span></code></a> 的值</p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">malloc</span></code>: 来自 C 标准库的系统分配, C 函数 <code class="xref c c-func docutils literal notranslate"><span class="pre">malloc()</span></code>, <code class="xref c c-func docutils literal notranslate"><span class="pre">calloc()</span></code>, <code class="xref c c-func docutils literal notranslate"><span class="pre">realloc()</span></code> and <code class="xref c c-func docutils literal notranslate"><span class="pre">free()</span></code></p></li>
|
||
<li><p><code class="docutils literal notranslate"><span class="pre">pymalloc</span></code>: <a class="reference internal" href="#pymalloc"><span class="std std-ref">pymalloc 内存分配器</span></a></p></li>
|
||
<li><p>"+ debug": 带有 <a class="reference internal" href="#c.PyMem_SetupDebugHooks" title="PyMem_SetupDebugHooks"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_SetupDebugHooks()</span></code></a> 安装的调试钩子</p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="customize-memory-allocators">
|
||
<h2>自定义内存分配器<a class="headerlink" href="#customize-memory-allocators" title="永久链接至标题">¶</a></h2>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.4 新版功能.</span></p>
|
||
</div>
|
||
<dl class="type">
|
||
<dt id="c.PyMemAllocatorEx">
|
||
<code class="sig-name descname">PyMemAllocatorEx</code><a class="headerlink" href="#c.PyMemAllocatorEx" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>用于描述内存块分配器的结构体。包含四个字段:</p>
|
||
<table class="docutils align-default">
|
||
<colgroup>
|
||
<col style="width: 60%" />
|
||
<col style="width: 40%" />
|
||
</colgroup>
|
||
<thead>
|
||
<tr class="row-odd"><th class="head"><p>域</p></th>
|
||
<th class="head"><p>含意</p></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">*ctx</span></code></p></td>
|
||
<td><p>作为第一个参数传入的用户上下文</p></td>
|
||
</tr>
|
||
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">void*</span> <span class="pre">malloc(void</span> <span class="pre">*ctx,</span> <span class="pre">size_t</span> <span class="pre">size)</span></code></p></td>
|
||
<td><p>分配一个内存块</p></td>
|
||
</tr>
|
||
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">void*</span> <span class="pre">calloc(void</span> <span class="pre">*ctx,</span> <span class="pre">size_t</span> <span class="pre">nelem,</span> <span class="pre">size_t</span> <span class="pre">elsize)</span></code></p></td>
|
||
<td><p>分配一个初始化为 0 的内存块</p></td>
|
||
</tr>
|
||
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">void*</span> <span class="pre">realloc(void</span> <span class="pre">*ctx,</span> <span class="pre">void</span> <span class="pre">*ptr,</span> <span class="pre">size_t</span> <span class="pre">new_size)</span></code></p></td>
|
||
<td><p>分配一个内存块或调整其大小</p></td>
|
||
</tr>
|
||
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">free(void</span> <span class="pre">*ctx,</span> <span class="pre">void</span> <span class="pre">*ptr)</span></code></p></td>
|
||
<td><p>释放一个内存块</p></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.5 版更改: </span>The <code class="xref c c-type docutils literal notranslate"><span class="pre">PyMemAllocator</span></code> structure was renamed to
|
||
<a class="reference internal" href="#c.PyMemAllocatorEx" title="PyMemAllocatorEx"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyMemAllocatorEx</span></code></a> and a new <code class="docutils literal notranslate"><span class="pre">calloc</span></code> field was added.</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
<dl class="type">
|
||
<dt id="c.PyMemAllocatorDomain">
|
||
<code class="sig-name descname">PyMemAllocatorDomain</code><a class="headerlink" href="#c.PyMemAllocatorDomain" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>用来识别分配器域的枚举类。域有:</p>
|
||
<dl class="macro">
|
||
<dt id="c.PYMEM_DOMAIN_RAW">
|
||
<code class="sig-name descname">PYMEM_DOMAIN_RAW</code><a class="headerlink" href="#c.PYMEM_DOMAIN_RAW" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>函数</p>
|
||
<ul class="simple">
|
||
<li><p><a class="reference internal" href="#c.PyMem_RawMalloc" title="PyMem_RawMalloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_RawMalloc()</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="#c.PyMem_RawRealloc" title="PyMem_RawRealloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_RawRealloc()</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="#c.PyMem_RawCalloc" title="PyMem_RawCalloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_RawCalloc()</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="#c.PyMem_RawFree" title="PyMem_RawFree"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_RawFree()</span></code></a></p></li>
|
||
</ul>
|
||
</dd></dl>
|
||
|
||
<dl class="macro">
|
||
<dt id="c.PYMEM_DOMAIN_MEM">
|
||
<code class="sig-name descname">PYMEM_DOMAIN_MEM</code><a class="headerlink" href="#c.PYMEM_DOMAIN_MEM" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>函数</p>
|
||
<ul class="simple">
|
||
<li><p><a class="reference internal" href="#c.PyMem_Malloc" title="PyMem_Malloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Malloc()</span></code></a>,</p></li>
|
||
<li><p><a class="reference internal" href="#c.PyMem_Realloc" title="PyMem_Realloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Realloc()</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="#c.PyMem_Calloc" title="PyMem_Calloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Calloc()</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="#c.PyMem_Free" title="PyMem_Free"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Free()</span></code></a></p></li>
|
||
</ul>
|
||
</dd></dl>
|
||
|
||
<dl class="macro">
|
||
<dt id="c.PYMEM_DOMAIN_OBJ">
|
||
<code class="sig-name descname">PYMEM_DOMAIN_OBJ</code><a class="headerlink" href="#c.PYMEM_DOMAIN_OBJ" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>函数</p>
|
||
<ul class="simple">
|
||
<li><p><a class="reference internal" href="#c.PyObject_Malloc" title="PyObject_Malloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Malloc()</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="#c.PyObject_Realloc" title="PyObject_Realloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Realloc()</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="#c.PyObject_Calloc" title="PyObject_Calloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Calloc()</span></code></a></p></li>
|
||
<li><p><a class="reference internal" href="#c.PyObject_Free" title="PyObject_Free"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Free()</span></code></a></p></li>
|
||
</ul>
|
||
</dd></dl>
|
||
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="c.PyMem_GetAllocator">
|
||
void <code class="sig-name descname">PyMem_GetAllocator</code><span class="sig-paren">(</span><a class="reference internal" href="#c.PyMemAllocatorDomain" title="PyMemAllocatorDomain">PyMemAllocatorDomain</a><em> domain</em>, <a class="reference internal" href="#c.PyMemAllocatorEx" title="PyMemAllocatorEx">PyMemAllocatorEx</a><em> *allocator</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyMem_GetAllocator" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>获取指定域的内存块分配器。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="c.PyMem_SetAllocator">
|
||
void <code class="sig-name descname">PyMem_SetAllocator</code><span class="sig-paren">(</span><a class="reference internal" href="#c.PyMemAllocatorDomain" title="PyMemAllocatorDomain">PyMemAllocatorDomain</a><em> domain</em>, <a class="reference internal" href="#c.PyMemAllocatorEx" title="PyMemAllocatorEx">PyMemAllocatorEx</a><em> *allocator</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyMem_SetAllocator" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>设置指定域的内存块分配器。</p>
|
||
<p>当请求零字节时,新的分配器必须返回一个独特的非 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> 指针。</p>
|
||
<p>对于 <a class="reference internal" href="#c.PYMEM_DOMAIN_RAW" title="PYMEM_DOMAIN_RAW"><code class="xref c c-data docutils literal notranslate"><span class="pre">PYMEM_DOMAIN_RAW</span></code></a> 域,分配器必须是线程安全的:当分配器被调用时,不持有 <a class="reference internal" href="../glossary.html#term-global-interpreter-lock"><span class="xref std std-term">全局解释器锁</span></a> 。</p>
|
||
<p>如果新的分配器不是钩子(不调用之前的分配器),必须调用 <a class="reference internal" href="#c.PyMem_SetupDebugHooks" title="PyMem_SetupDebugHooks"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_SetupDebugHooks()</span></code></a> 函数在新分配器上重新安装调试钩子。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="c.PyMem_SetupDebugHooks">
|
||
void <code class="sig-name descname">PyMem_SetupDebugHooks</code><span class="sig-paren">(</span>void<span class="sig-paren">)</span><a class="headerlink" href="#c.PyMem_SetupDebugHooks" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>设置检测 Python 内存分配器函数中错误的钩子。</p>
|
||
<p>新分配的内存由字节 <code class="docutils literal notranslate"><span class="pre">0xCD</span></code> ( <code class="docutils literal notranslate"><span class="pre">CLEANBYTE</span></code> ) 填充,释放的内存由字节 <code class="docutils literal notranslate"><span class="pre">0xDD</span></code> ( <code class="docutils literal notranslate"><span class="pre">DEADBYTE</span></code> )填充。内存块被 "禁止字节" 包围( <code class="docutils literal notranslate"><span class="pre">FORBIDDENBYTE</span></code> :字节 <code class="docutils literal notranslate"><span class="pre">0xFD</span></code> )。</p>
|
||
<p>运行时检查:</p>
|
||
<ul class="simple">
|
||
<li><p>检测对 API 的违反,例如:对用 <a class="reference internal" href="#c.PyMem_Malloc" title="PyMem_Malloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Malloc()</span></code></a> 分配的缓冲区调用 <a class="reference internal" href="#c.PyObject_Free" title="PyObject_Free"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Free()</span></code></a> 。</p></li>
|
||
<li><p>检测缓冲区起始位置前的写入(缓冲区下溢)。</p></li>
|
||
<li><p>检测缓冲区终止位置后的写入(缓冲区溢出)。</p></li>
|
||
<li><p>检测当调用 <a class="reference internal" href="#c.PYMEM_DOMAIN_OBJ" title="PYMEM_DOMAIN_OBJ"><code class="xref c c-data docutils literal notranslate"><span class="pre">PYMEM_DOMAIN_OBJ</span></code></a> (如: <a class="reference internal" href="#c.PyObject_Malloc" title="PyObject_Malloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Malloc()</span></code></a>) 和 <a class="reference internal" href="#c.PYMEM_DOMAIN_MEM" title="PYMEM_DOMAIN_MEM"><code class="xref c c-data docutils literal notranslate"><span class="pre">PYMEM_DOMAIN_MEM</span></code></a> (如: <a class="reference internal" href="#c.PyMem_Malloc" title="PyMem_Malloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Malloc()</span></code></a>) 域的分配器函数时 <a class="reference internal" href="../glossary.html#term-global-interpreter-lock"><span class="xref std std-term">GIL</span></a> 已被保持。</p></li>
|
||
</ul>
|
||
<p>在出错时,调试钩子使用 <a class="reference internal" href="../library/tracemalloc.html#module-tracemalloc" title="tracemalloc: Trace memory allocations."><code class="xref py py-mod docutils literal notranslate"><span class="pre">tracemalloc</span></code></a> 模块来回溯内存块被分配的位置。只有当 <a class="reference internal" href="../library/tracemalloc.html#module-tracemalloc" title="tracemalloc: Trace memory allocations."><code class="xref py py-mod docutils literal notranslate"><span class="pre">tracemalloc</span></code></a> 正在追踪 Python 内存分配,并且内存块被追踪时,才会显示回溯。</p>
|
||
<p>如果 Python 是在调试模式下编译的,这些钩子是 <a class="reference internal" href="#default-memory-allocators"><span class="std std-ref">installed by default</span></a> 。环境变量 <span class="target" id="index-12"></span><a class="reference internal" href="../using/cmdline.html#envvar-PYTHONMALLOC"><code class="xref std std-envvar docutils literal notranslate"><span class="pre">PYTHONMALLOC</span></code></a> 可以用来在发布模式编译的 Python 上安装调试钩子。</p>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.6 版更改: </span>这个函数现在也适用于以 发布模式编译的 Python。在出错时,调试钩子现在使用 <a class="reference internal" href="../library/tracemalloc.html#module-tracemalloc" title="tracemalloc: Trace memory allocations."><code class="xref py py-mod docutils literal notranslate"><span class="pre">tracemalloc</span></code></a> 来回溯内存块被分配的位置。调试钩子现在也检查当 <a class="reference internal" href="#c.PYMEM_DOMAIN_OBJ" title="PYMEM_DOMAIN_OBJ"><code class="xref c c-data docutils literal notranslate"><span class="pre">PYMEM_DOMAIN_OBJ</span></code></a> 和 <a class="reference internal" href="#c.PYMEM_DOMAIN_MEM" title="PYMEM_DOMAIN_MEM"><code class="xref c c-data docutils literal notranslate"><span class="pre">PYMEM_DOMAIN_MEM</span></code></a> 域的函数被调用时,全局解释器锁是否被持有。</p>
|
||
</div>
|
||
<div class="versionchanged">
|
||
<p><span class="versionmodified changed">在 3.8 版更改: </span>字节模式 <code class="docutils literal notranslate"><span class="pre">0xCB</span></code> (<code class="docutils literal notranslate"><span class="pre">CLEANBYTE</span></code>)、 <code class="docutils literal notranslate"><span class="pre">0xDB</span></code> (<code class="docutils literal notranslate"><span class="pre">DEADBYTE</span></code>) 和 <code class="docutils literal notranslate"><span class="pre">0xFB</span></code> (<code class="docutils literal notranslate"><span class="pre">FORBIDDENBYTE</span></code>) 已被 <code class="docutils literal notranslate"><span class="pre">0xCD</span></code> 、 <code class="docutils literal notranslate"><span class="pre">0xDD</span></code> 和 <code class="docutils literal notranslate"><span class="pre">0xFD</span></code> 替代以使用与 Windows CRT 调试 <code class="docutils literal notranslate"><span class="pre">malloc()</span></code> 和 <code class="docutils literal notranslate"><span class="pre">free()</span></code> 相同的值。</p>
|
||
</div>
|
||
</dd></dl>
|
||
|
||
</section>
|
||
<section id="the-pymalloc-allocator">
|
||
<span id="pymalloc"></span><h2>pymalloc 分配器<a class="headerlink" href="#the-pymalloc-allocator" title="永久链接至标题">¶</a></h2>
|
||
<p>Python 有为具有短生命周期的小对象(小于或等于 512 字节)优化的 <em>pymalloc</em> 分配器。它使用固定大小为 256 KiB 的称为 "arenas" 的内存映射。对于大于512字节的分配,它回到使用 <a class="reference internal" href="#c.PyMem_RawMalloc" title="PyMem_RawMalloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_RawMalloc()</span></code></a> 和 <a class="reference internal" href="#c.PyMem_RawRealloc" title="PyMem_RawRealloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_RawRealloc()</span></code></a> 。</p>
|
||
<p><em>pymalloc</em> 是 <a class="reference internal" href="#c.PYMEM_DOMAIN_MEM" title="PYMEM_DOMAIN_MEM"><code class="xref c c-data docutils literal notranslate"><span class="pre">PYMEM_DOMAIN_MEM</span></code></a> (例如: <a class="reference internal" href="#c.PyMem_Malloc" title="PyMem_Malloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Malloc()</span></code></a>) 和 <a class="reference internal" href="#c.PYMEM_DOMAIN_OBJ" title="PYMEM_DOMAIN_OBJ"><code class="xref c c-data docutils literal notranslate"><span class="pre">PYMEM_DOMAIN_OBJ</span></code></a> (例如: <a class="reference internal" href="#c.PyObject_Malloc" title="PyObject_Malloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Malloc()</span></code></a>) 域的 <a class="reference internal" href="#default-memory-allocators"><span class="std std-ref">默认分配器</span></a> 。</p>
|
||
<p>arena 分配器使用以下函数:</p>
|
||
<ul class="simple">
|
||
<li><p>Windows 上的 <code class="xref c c-func docutils literal notranslate"><span class="pre">VirtualAlloc()</span></code> 和 <code class="xref c c-func docutils literal notranslate"><span class="pre">VirtualFree()</span></code> ,</p></li>
|
||
<li><p><code class="xref c c-func docutils literal notranslate"><span class="pre">mmap()</span></code> 和 <code class="xref c c-func docutils literal notranslate"><span class="pre">munmap()</span></code> ,如果可用,</p></li>
|
||
<li><p>否则, <code class="xref c c-func docutils literal notranslate"><span class="pre">malloc()</span></code> 和 <code class="xref c c-func docutils literal notranslate"><span class="pre">free()</span></code> 。</p></li>
|
||
</ul>
|
||
<section id="customize-pymalloc-arena-allocator">
|
||
<h3>自定义 pymalloc Arena 分配器<a class="headerlink" href="#customize-pymalloc-arena-allocator" title="永久链接至标题">¶</a></h3>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.4 新版功能.</span></p>
|
||
</div>
|
||
<dl class="type">
|
||
<dt id="c.PyObjectArenaAllocator">
|
||
<code class="sig-name descname">PyObjectArenaAllocator</code><a class="headerlink" href="#c.PyObjectArenaAllocator" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>用来描述一个 arena 分配器的结构体。这个结构体有三个字段:</p>
|
||
<table class="docutils align-default">
|
||
<colgroup>
|
||
<col style="width: 56%" />
|
||
<col style="width: 44%" />
|
||
</colgroup>
|
||
<thead>
|
||
<tr class="row-odd"><th class="head"><p>域</p></th>
|
||
<th class="head"><p>含意</p></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">*ctx</span></code></p></td>
|
||
<td><p>作为第一个参数传入的用户上下文</p></td>
|
||
</tr>
|
||
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">void*</span> <span class="pre">alloc(void</span> <span class="pre">*ctx,</span> <span class="pre">size_t</span> <span class="pre">size)</span></code></p></td>
|
||
<td><p>分配一块 size 字节的区域</p></td>
|
||
</tr>
|
||
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">free(void</span> <span class="pre">*ctx,</span> <span class="pre">void</span> <span class="pre">*ptr,</span> <span class="pre">size_t</span> <span class="pre">size)</span></code></p></td>
|
||
<td><p>释放一块区域</p></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="c.PyObject_GetArenaAllocator">
|
||
void <code class="sig-name descname">PyObject_GetArenaAllocator</code><span class="sig-paren">(</span><a class="reference internal" href="#c.PyObjectArenaAllocator" title="PyObjectArenaAllocator">PyObjectArenaAllocator</a><em> *allocator</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyObject_GetArenaAllocator" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>获取 arena 分配器</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="c.PyObject_SetArenaAllocator">
|
||
void <code class="sig-name descname">PyObject_SetArenaAllocator</code><span class="sig-paren">(</span><a class="reference internal" href="#c.PyObjectArenaAllocator" title="PyObjectArenaAllocator">PyObjectArenaAllocator</a><em> *allocator</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyObject_SetArenaAllocator" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>设置 arena 分配器</p>
|
||
</dd></dl>
|
||
|
||
</section>
|
||
</section>
|
||
<section id="tracemalloc-c-api">
|
||
<h2>tracemalloc C API<a class="headerlink" href="#tracemalloc-c-api" title="永久链接至标题">¶</a></h2>
|
||
<div class="versionadded">
|
||
<p><span class="versionmodified added">3.7 新版功能.</span></p>
|
||
</div>
|
||
<dl class="function">
|
||
<dt id="c.PyTraceMalloc_Track">
|
||
int <code class="sig-name descname">PyTraceMalloc_Track</code><span class="sig-paren">(</span>unsigned int<em> domain</em>, uintptr_t<em> ptr</em>, size_t<em> size</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyTraceMalloc_Track" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>在 <a class="reference internal" href="../library/tracemalloc.html#module-tracemalloc" title="tracemalloc: Trace memory allocations."><code class="xref py py-mod docutils literal notranslate"><span class="pre">tracemalloc</span></code></a> 模块中跟踪一个已分配的内存块。</p>
|
||
<p>成功时返回 <code class="docutils literal notranslate"><span class="pre">0</span></code>,出错时返回 <code class="docutils literal notranslate"><span class="pre">-1</span></code> (无法分配内存来保存跟踪信息)。 如果禁用了 tracemalloc 则返回 <code class="docutils literal notranslate"><span class="pre">-2</span></code>。</p>
|
||
<p>如果内存块已被跟踪,则更新现有跟踪信息。</p>
|
||
</dd></dl>
|
||
|
||
<dl class="function">
|
||
<dt id="c.PyTraceMalloc_Untrack">
|
||
int <code class="sig-name descname">PyTraceMalloc_Untrack</code><span class="sig-paren">(</span>unsigned int<em> domain</em>, uintptr_t<em> ptr</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyTraceMalloc_Untrack" title="永久链接至目标">¶</a></dt>
|
||
<dd><p>在 <a class="reference internal" href="../library/tracemalloc.html#module-tracemalloc" title="tracemalloc: Trace memory allocations."><code class="xref py py-mod docutils literal notranslate"><span class="pre">tracemalloc</span></code></a> 模块中取消跟踪一个已分配的内存块。 如果内存块未被跟踪则不执行任何操作。</p>
|
||
<p>如果 tracemalloc 被禁用则返回 <code class="docutils literal notranslate"><span class="pre">-2</span></code>,否则返回 <code class="docutils literal notranslate"><span class="pre">0</span></code>。</p>
|
||
</dd></dl>
|
||
|
||
</section>
|
||
<section id="examples">
|
||
<span id="memoryexamples"></span><h2>例子<a class="headerlink" href="#examples" title="永久链接至标题">¶</a></h2>
|
||
<p>以下是来自 <a class="reference internal" href="#memoryoverview"><span class="std std-ref">概述</span></a> 小节的示例,经过重写以使 I/O 缓冲区是通过使用第一个函数集从 Python 堆中分配的:</p>
|
||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">res</span><span class="p">;</span>
|
||
<span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">buf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="p">)</span><span class="w"> </span><span class="n">PyMem_Malloc</span><span class="p">(</span><span class="n">BUFSIZ</span><span class="p">);</span><span class="w"> </span><span class="cm">/* for I/O */</span>
|
||
|
||
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">buf</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span>
|
||
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">PyErr_NoMemory</span><span class="p">();</span>
|
||
<span class="cm">/* ...Do some I/O operation involving buf... */</span>
|
||
<span class="n">res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyBytes_FromString</span><span class="p">(</span><span class="n">buf</span><span class="p">);</span>
|
||
<span class="n">PyMem_Free</span><span class="p">(</span><span class="n">buf</span><span class="p">);</span><span class="w"> </span><span class="cm">/* allocated with PyMem_Malloc */</span>
|
||
<span class="k">return</span><span class="w"> </span><span class="n">res</span><span class="p">;</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>使用面向类型函数集的相同代码:</p>
|
||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">res</span><span class="p">;</span>
|
||
<span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">buf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyMem_New</span><span class="p">(</span><span class="kt">char</span><span class="p">,</span><span class="w"> </span><span class="n">BUFSIZ</span><span class="p">);</span><span class="w"> </span><span class="cm">/* for I/O */</span>
|
||
|
||
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">buf</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span>
|
||
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">PyErr_NoMemory</span><span class="p">();</span>
|
||
<span class="cm">/* ...Do some I/O operation involving buf... */</span>
|
||
<span class="n">res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyBytes_FromString</span><span class="p">(</span><span class="n">buf</span><span class="p">);</span>
|
||
<span class="n">PyMem_Del</span><span class="p">(</span><span class="n">buf</span><span class="p">);</span><span class="w"> </span><span class="cm">/* allocated with PyMem_New */</span>
|
||
<span class="k">return</span><span class="w"> </span><span class="n">res</span><span class="p">;</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>请注意在以上两个示例中,缓冲区总是通过归属于相同集的函数来操纵的。 事实上,对于一个给定的内存块必须使用相同的内存 API 族,以便使得混合不同分配器的风险减至最低。 以下代码序列包含两处错误,其中一个被标记为 <em>fatal</em> 因为它混合了两种在不同堆上操作的不同分配器。</p>
|
||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">buf1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyMem_New</span><span class="p">(</span><span class="kt">char</span><span class="p">,</span><span class="w"> </span><span class="n">BUFSIZ</span><span class="p">);</span>
|
||
<span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">buf2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="p">)</span><span class="w"> </span><span class="n">malloc</span><span class="p">(</span><span class="n">BUFSIZ</span><span class="p">);</span>
|
||
<span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">buf3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="p">)</span><span class="w"> </span><span class="n">PyMem_Malloc</span><span class="p">(</span><span class="n">BUFSIZ</span><span class="p">);</span>
|
||
<span class="p">...</span>
|
||
<span class="n">PyMem_Del</span><span class="p">(</span><span class="n">buf3</span><span class="p">);</span><span class="w"> </span><span class="cm">/* Wrong -- should be PyMem_Free() */</span>
|
||
<span class="n">free</span><span class="p">(</span><span class="n">buf2</span><span class="p">);</span><span class="w"> </span><span class="cm">/* Right -- allocated via malloc() */</span>
|
||
<span class="n">free</span><span class="p">(</span><span class="n">buf1</span><span class="p">);</span><span class="w"> </span><span class="cm">/* Fatal -- should be PyMem_Del() */</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>除了旨在处理来自 Python 堆的原始内存块的函数之外, Python 中的对象是通过 <a class="reference internal" href="allocation.html#c.PyObject_New" title="PyObject_New"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_New()</span></code></a>, <a class="reference internal" href="allocation.html#c.PyObject_NewVar" title="PyObject_NewVar"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_NewVar()</span></code></a> 和 <a class="reference internal" href="allocation.html#c.PyObject_Del" title="PyObject_Del"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Del()</span></code></a> 来分配和释放的。</p>
|
||
<p>这些将在有关如何在 C 中定义和实现新对象类型的下一章中讲解。</p>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||
<div class="sphinxsidebarwrapper">
|
||
<h3><a href="../contents.html">目录</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#">内存管理</a><ul>
|
||
<li><a class="reference internal" href="#overview">概述</a></li>
|
||
<li><a class="reference internal" href="#raw-memory-interface">原始内存接口</a></li>
|
||
<li><a class="reference internal" href="#memory-interface">内存接口</a></li>
|
||
<li><a class="reference internal" href="#object-allocators">对象分配器</a></li>
|
||
<li><a class="reference internal" href="#default-memory-allocators">默认内存分配器</a></li>
|
||
<li><a class="reference internal" href="#customize-memory-allocators">自定义内存分配器</a></li>
|
||
<li><a class="reference internal" href="#the-pymalloc-allocator">pymalloc 分配器</a><ul>
|
||
<li><a class="reference internal" href="#customize-pymalloc-arena-allocator">自定义 pymalloc Arena 分配器</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#tracemalloc-c-api">tracemalloc C API</a></li>
|
||
<li><a class="reference internal" href="#examples">例子</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<h4>上一个主题</h4>
|
||
<p class="topless"><a href="init_config.html"
|
||
title="上一章">Python初始化配置</a></p>
|
||
<h4>下一个主题</h4>
|
||
<p class="topless"><a href="objimpl.html"
|
||
title="下一章">对象实现支持</a></p>
|
||
<div role="note" aria-label="source link">
|
||
<h3>本页</h3>
|
||
<ul class="this-page-menu">
|
||
<li><a href="../bugs.html">报告 Bug</a></li>
|
||
<li>
|
||
<a href="https://github.com/python/cpython/blob/3.8/Doc/c-api/memory.rst"
|
||
rel="nofollow">显示源代码
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="clearer"></div>
|
||
</div>
|
||
<div class="related" role="navigation" aria-label="related navigation">
|
||
<h3>导航</h3>
|
||
<ul>
|
||
<li class="right" style="margin-right: 10px">
|
||
<a href="../genindex.html" title="总目录"
|
||
>索引</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python 模块索引"
|
||
>模块</a> |</li>
|
||
<li class="right" >
|
||
<a href="objimpl.html" title="对象实现支持"
|
||
>下一页</a> |</li>
|
||
<li class="right" >
|
||
<a href="init_config.html" title="Python初始化配置"
|
||
>上一页</a> |</li>
|
||
|
||
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
|
||
<li><a href="https://www.python.org/">Python</a> »</li>
|
||
<li class="switchers">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<div class="version_switcher_placeholder"></div>
|
||
</li>
|
||
<li>
|
||
|
||
</li>
|
||
<li id="cpython-language-and-version">
|
||
<a href="../index.html">3.8.20 Documentation</a> »
|
||
</li>
|
||
|
||
<li class="nav-item nav-item-1"><a href="index.html" >Python/C API 参考手册</a> »</li>
|
||
<li class="right">
|
||
|
||
|
||
<div class="inline-search" role="search">
|
||
<form class="inline-search" action="../search.html" method="get">
|
||
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
|
||
<input type="submit" value="转向" />
|
||
<input type="hidden" name="check_keywords" value="yes" />
|
||
<input type="hidden" name="area" value="default" />
|
||
</form>
|
||
</div>
|
||
|
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
<div class="footer">
|
||
© <a href="../copyright.html">版权所有</a> 2001-2024, Python Software Foundation.
|
||
<br />
|
||
This page is licensed under the Python Software Foundation License Version 2.
|
||
<br />
|
||
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
|
||
<br />
|
||
|
||
<br />
|
||
|
||
The Python Software Foundation is a non-profit corporation.
|
||
<a href="https://www.python.org/psf/donations/">Please donate.</a>
|
||
<br />
|
||
<br />
|
||
|
||
最后更新于 12月 09, 2024.
|
||
<a href="https://docs.python.org/3/bugs.html">Found a bug</a>?
|
||
<br />
|
||
|
||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 2.4.4.
|
||
</div>
|
||
|
||
</body>
|
||
</html> |