库级别动态内存分配为动态内存分配提供了一个易于使用的接口。
最常用的接口包括:
其他动态内存分配接口包括 memalign(3C)、valloc(3C) 和 realloc(3C)
free 可用于将通过 malloc、calloc、realloc、memalign 或 valloc 获取的内存返回到系统内存。尝试释放不是由动态内存分配接口所保留的块是一个错误,会导致进程崩溃。
calloc 可用于返回一个指向初始化为零的内存块的指针。可以通过 cfree 或 free 将 calloc 保留的内存返回到系统。内存会进行分配并对齐,以包含具有指定大小的指定元素数的数组。
realloc 可用于更改分配给进程的内存块的大小,使用 realloc 可增大或减小分配的内存块的大小。realloc 是缩减内存分配而不会导致问题的唯一方法。重新分配的块在内存中的位置可能会更改,但是在分配大小更改之前的内容将保持不变。
Sun™ WorkShop 工具包有助于查找和消除在使用动态内存时出现的错误。Sun WorkShop 的运行时检查 (Run Time Checking, RTC) 工具使用本节中介绍的函数来查找使用动态内存时的错误。
RTC 不需要使用 -g 对程序进行编译以查找所有错误。不过,有时需要符号 (-g) 信息,以保证某些错误(尤其是从未初始化内存中读取的错误)的正确性。因此,如果没有可用的符号信息,则某些错误会受到抑制。这些错误包括 rui(针对 a.out)和 rui + aib + air(针对共享库)。可以使用 suppress 和 unsuppress 来更改此行为。
-access 选项可用于启动访问检查。 RTC 将报告以下错误:
错误释放
重复释放
未对齐的释放
未对齐的读取
未对齐的写入
内存不足
从未分配的内存读取
从未初始化的内存读取
写入只读内存
写入未分配的内存
缺省行为是在检测到每个访问错误之后停止进程。可以使用 rtc_auto_continue dbxenv 变量更改此行为。如果设置为 on,则 RTC 会将访问错误记录到文件中。文件名由 rtc_error_log_file_name dbxenv 变量的值确定。缺省情况下,仅在每个唯一的访问错误首次发生时报告该错误。可使用 rtc_auto_suppress dbxenv 变量更改此行为。此变量的缺省设置为 on。
-leaks 选项可用于启动泄漏检查。 RTC 将报告以下错误:
可能的内存泄漏-仅有的指针指向块的中间位置
可能的内存泄漏-指向块的指针仅存在于寄存器中
内存泄漏-没有指向块的指针
启动泄漏检查之后,在程序退出时会获取自动生成的泄漏报告。此时会报告包括潜在泄漏在内的所有泄漏。缺省情况下,将生成非详细报告。此缺省行为由 dbxenv rtc_mel_at_exit 控制。不过,可以随时要求提供泄漏报告。
报告泄漏时,-frames n 最多可显示 n 个不同的栈帧。-match m 变量用于合并泄漏。如果进行分配时两个或多个泄漏的调用栈与 m 帧匹配,则会在单个合并的泄漏报告中报告这些泄漏。n 的缺省值是 8 或 m 值之间的较大者。n 的最大值为 16。m 的缺省值为 2。
-memuse 选项可用于启动内存使用 (memuse) 检查。如果使用 check -memuse,则表示同时启用了 check -leaks。除程序退出时获取泄漏报告之外,您还会获得一个列出使用中的块 (biu) 的报告。缺省情况下,将生成有关使用中的块的非详细报告。此缺省行为由 dbxenv rtc_biu_at_exit 控制。在程序执行过程中,可随时查看程序中的内存所分配到的位置。
-frames n 和 -match m 变量的作用如以下部分所述。
与 check -access; check -memuse [-frames n] [-match m] 等效。rtc_biu_at_exit dbxenv 变量的值不会随 check -all 进行更改。因此,缺省情况下,退出时不会生成任何内存使用报告。
与 funcs files loadobjects 中的 check -all; suppress all; unsuppress all 等效。使用此选项可以将 RTC 重点用于所需的位置。
本节介绍其他内存控制接口。
sysconf(3C) 可用于返回与系统相关的内存页的大小。为便于移植,应用程序不应嵌入用于指定页面大小的任何常量。请注意,即使在相同指令集的执行中,变化的页面大小也很常见。
mprotect(2) 可用于为指定地址范围内的所有页面提供指定的保护。保护不能超出底层对象所允许的权限。
中断点 (break) 是进程映像中栈外部的最大的有效数据地址。程序开始执行时,execve(2) 通常会将中断点 (break) 值设置为程序及其数据存储所定义的最大地址。
使用 brk(2) 可将中断点 (break) 设置为更大的地址。您还可以使用 sbrk(2) 向进程的数据段中添加一个存储增量。通过调用 getrlimit(2) 可以获取数据段的最大可能大小。
caddr_t brk(caddr_t addr); caddr_t sbrk(intptr_t incr);