多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# 44.3\. 内存管理 **Table of Contents** + [SPI_palloc](#calibre_link-1737) -- 在上层执行器环境里分配内存 + [SPI_repalloc](#calibre_link-1738) -- 在上层执行器环境里重新分配内存 + [SPI_pfree](#calibre_link-1739) -- 在上层执行器环境里释放内存 + [SPI_copytuple](#calibre_link-1740) -- 在上层执行者环境里制作一个行的拷贝 + [SPI_returntuple](#calibre_link-1741) -- 准备把一个行当作 Datum 返回 + [SPI_modifytuple](#calibre_link-1742) -- 通过替换一个给出行的选定的字段创建一行 + [SPI_freetuple](#calibre_link-1743) -- 释放在上层执行者环境里分配的一行 + [SPI_freetuptable](#calibre_link-1744) -- 释放一个由`SPI_execute`或者类似的函数创建的行集 + [SPI_freeplan](#calibre_link-1745) --  释放一个前面保存的预备语句 PostgreSQL在_内存环境_中分配内存, 它提供了在许多地方分配的,有着不同的生命期的许多内存块的一个方便的管理方法。 删除一个环境则释放所有在其内部分配的内存。因此,没必要跟踪独立的对象以避免内存泄漏; 而是只要管理少量的环境。`palloc`和相关的函数从"当前" 的环境中分配内存。 `SPI_connect`创建一个新的内存环境并且将其标记为当前的环境。 `SPI_finish`恢复前一个内存环境并且删除`SPI_connect` 创建的环境。这些动作确保在你的过程中分配的临时内存在过程结尾的时候都被回收,避免内存泄漏。 不过,如果你的过程需要返回一个已分配的内存对象(比如一个传递引用的数据类型), 那么你就不能用`palloc`分配返回的对象, 至少是不能在你已经和 SPI 连接上的时候。如果你试图这么做, 那么该对象将在`SPI_finish`的时候被释放, 因而你的过程就不能可靠地工作了!要解决这个问题,使用`SPI_palloc` 分配内存给你的返回对象。`SPI_palloc`从"上层执行者环境" 中分配空间,也就是调用`SPI_connect`时候的当前环境内存环境, 该环境是从你的过程返回数值的正确环境。 如果还没有连接到 SPI 的时候调用它,`SPI_palloc` 的行为和简单的`palloc`一样。在一个过程和 SPI 管理器连接之前, 当前的内存环境是上层执行者环境,因此所有该过程使用`palloc` 或者 SPI 工具函数分配的空间都是在这个环境中分配的。 在调用`SPI_connect`之后,当前环境是该过程私有的, 由`SPI_connect`制作的环境。所有通过`palloc`、 `repalloc`或者 SPI 工具函数(除了`SPI_copytuple`、 `SPI_returntuple`、`SPI_modifytuple`和 `SPI_palloc`)分配的内存都是在这个环境中分配的。 如果一个过程与 SPI 管理器断开(通过`SPI_finish`), 那么当前环境恢复为上层执行器环境, 并且所有在该过程的内存环境中分配的内存都释放掉并且不能再次使用! 所有在本节内描述的函数都可以在已连接的和未连接的过程中使用。 在未连接的过程中,他们的行为和下层的原始后端函数(`palloc`等)相同。