45.3. 内存管理

目录
SPI_palloc -- 在上层执行器上下文中分配内存
SPI_repalloc -- 在上层执行器上下文中重分配内存
SPI_pfree -- 在上层执行器上下文中释放内存
SPI_copytuple -- 在上层执行器上下文中创建一行的拷贝
SPI_returntuple -- 准备把一个元组返回为一个 Datum
SPI_modifytuple -- 通过替换一个给定行的选定域来创建一行
SPI_freetuple -- 释放一个在上层执行器上下文中分配的行
SPI_freetuptable -- 释放一个由SPI_execute 或者类似函数创建的行集合
SPI_freeplan -- 释放一个之前保存的预备语句

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)会被作为当前上 下文。所有用pallocrepalloc或者 SPI 功能函数(除了 SPI_copytupleSPI_returntupleSPI_modifytupleSPI_palloc)分配的内存都在这个上下文中。 当一个过程从 SPI 管理器断开连接时(通过 SPI_finish),当前上下文被恢复到上层的 执行器上下文,并且在该过程的内存上下文中分配的内存都会被释放, 之后再不能被使用。

这一节中描述的所有函数都可以在已连接和未连接的过程中使用。在 一个未连接的过程中,它们的行为和底层的普通服务器函数( palloc等)相同。