Swift的UnsafeMutablePointer< Float>.allocate(...)是否实际分配内存?

0ve6wy6x  于 2022-12-10  发布在  Swift
关注(0)|答案(2)|浏览(114)

我正在尝试理解Swift的不安全指针API,以便操纵音频样本。
不可变的指针变量(UnsafePointer、UnsafeRawPointer、UnsafeBufferPointer)对我来说很有意义,它们都是用来以只读方式引用以前分配的内存区域。
然而,可变变量(UnsafeMutablePointer、UnsafeMutableRawPointer)被记录为实际分配底层内存。
静态函数分配(容量:整数)
为指定数量的Pointee类型示例分配未初始化的内存
然而,没有提到UnsafeMutablePointer.allocate(size)可能会失败,因此它不能实际分配内存。相反,如果它确实分配了实际的内存,你怎么知道它是否失败呢?
任何见解都将不胜感激。

mu0hgdu0

mu0hgdu01#

我决定对此进行测试。我在CodeRunner中运行了以下程序:

import Foundation

sleep(10)

在执行sleep函数时,CodeRunner报告说这占用了我的机器上5.6 MB的RAM,这是我们的基线。
我接着试了这个程序:

import Foundation

for _ in 0..<1000000 {
    let ptr = UnsafeMutablePointer<Float>.allocate(capacity: 1)
}

sleep(10)

现在,CodeRunner报告了5. 8 MB的RAM使用量。比以前多了一点,但肯定不是这应该占用的额外4 MB。
最后,我为指针分配了一些内容:

import Foundation

for _ in 0..<1000000 {
    let ptr = UnsafeMutablePointer<Float>.allocate(capacity: 1)
    ptr.pointee = 0
}

sleep(10)

突然,程序占用了21.5 MB的RAM,最终使我们预期的RAM使用量增加,尽管比我预期的要大。
在CodeRunner中创建一个配置文件,在启用优化的情况下进行编译,似乎对我所看到的行为没有影响。
因此,令人惊讶的是,对UnsafeMutablePointer.allocate的调用实际上并没有立即分配内存。

ilmyapht

ilmyapht2#

操作系统在内存分配方面有很多欺骗行为。如果你请求一个大小为N的内存块,但实际上并没有在里面放任何东西,操作系统很可能会说“当然你可以有一个内存块,给你”,而不会对它做任何事情。它实际上更像是一个承诺,当程序使用内存时,内存将是可用的。
即使是像下面这样一个非常简单的C程序,macOS的Activity Monitor也会首先报告945 kB,然后在调用malloc(分配内存)后报告961 kB,最后在用零填充分配的内存后报告257.1 MB。
从程序的Angular 来看,整数数组所需的全部256 MB在调用malloc后立即可用,但这实际上是一个谎言。

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char const *argv[])
{
    int count = 64*1024*1024;
    printf("Step 1: No memory allocated yet. Check memory usage for baseline, then press enter to continue (1/3)");
    getchar();

    /* Allocate big block of memory */
    int *p = malloc(count*sizeof(int));
    if (p == NULL)  return 1; // failed to allocate
    printf("Step 2: Memory allocated. Check memory usage, then press any key to continue (2/3)");
    getchar();

    /* Fill with zeroes */
    for (int i=0; i < count; i++) {
        p[i] = 0;
    }
    printf("Step 3: Memory filled with zeroes. Check memory usage, then press any key to continue (3/3)");
    getchar();

    return 0;
}

相关问题