代码之家  ›  专栏  ›  技术社区  ›  Matt Joiner

将指针传递到保证为零的内存

  •  2
  • Matt Joiner  · 技术社区  · 15 年前

    我需要在一个文件中把不同大小的记录归零。为此,我正在分配虚拟记录, memset

    是否有一个区域可以保证总是归零(并且有足够大的大小),我可以指出它,从而消除重复分配和归零内存的需要?

    9 回复  |  直到 15 年前
        1
  •  8
  •   Gilles 'SO- stop being evil'    15 年前

    如果记录大小有合理的上限,则分配一个包含零的全局只读变量(因为它是一个静态的duration对象,所以它会自动初始化为零。)

    const unsigned char zero_filled_buffer[MAX_RECORD_SIZE]; /*at file scope*/
    

    如果写函数是C fwrite 或POSIX write 或其他功能,您可以(必须,例如 )在循环中调用它,这样缓冲区就不必像最大的记录那么大,就像一次写入的最大数据块一样大。

    在典型的托管实现中,这样的变量将占用可执行文件中的零空间。 补充 :请注意,就C标准而言,上述声明完全等同于 const unsigned char zero_filled_buffer[MAX_RECORD_SIZE] = {0}; 但是,如果显式地添加 = {0} 但如果你不使用初始值。

    具有虚拟内存的系统上的智能程序加载器可以利用虚拟内存系统为所有这些对象使用一个共享的只读零填充物理RAM页;我不知道在实践中有没有。 补充 :例如,Linux(Debian lenny amd64)没有。

    另一种POSIX方法是 mmap memset 将缓冲区归零。

        2
  •  3
  •   Sinan Ünür    15 年前

    看到了吗 calloc .

    这个 calloc() 函数应为数组分配未使用的空间 nelem 每个元素的字节大小 elsize . 空间应初始化为所有位 0 .

    或者(我没有试过这个),如果你不想 任何 你完全可以 open 和/或 mmap /dev/zero 阅读 record_size 块并将它们写入要覆盖记录的文件中。

        3
  •  2
  •   hroptatyr    15 年前

    mmap() 会给你一个零填充的缓冲区。 缺点是您不能只分配所需的内存,而只能分配页面大小的倍数

    #include <unistd.h>
    long sz = sysconf(_SC_PAGESIZE);
    
        4
  •  1
  •   Phil Miller    15 年前

    是的,只要分配一个足够大的块来容纳这些记录,然后将其归零一次。每次都将该块的地址传递给write函数,并将实际要归零的记录大小传递给write函数。传递缓冲区进行写入并不会使其过期或发生任何事情。记住,写也不会释放你传递的缓冲区;那由你决定。

        5
  •  1
  •   thomasrutter    15 年前

    然后,无论何时需要将指针传递给已归零的内存,都可以将指针传递给所分配的块内的内存。

        6
  •  1
  •   supercat    15 年前

    在大多数实现中,地址空间中没有一部分没有映射到RAM,但是当读取时,它将无害地读取零。有这样的东西也许不错,但我不知道。

        7
  •  0
  •   Behrooz    15 年前

    使用系统信息API获取系统页面大小(我只是记不清确切的名称),分配1页内存,将其设置为零,反复按顺序写入。

        8
  •  0
  •   Will    15 年前

    轮廓!

    *即使使用闪存驱动器

        9
  •  0
  •   Matt Joiner    15 年前

    这里有一个保证工作,运行时的可能性(编译时使用 gcc zeroed_mem_region.c -Wall -std=gnu99

    #include <sys/mman.h>
    #include <assert.h>
    #include <stdio.h>
    
    size_t const zeroed_size = 512;
    char const *zeroed;
    
    int main()
    {
        zeroed = mmap(
                NULL,
                zeroed_size,
                PROT_READ,
                MAP_PRIVATE|MAP_ANONYMOUS,
                -1,
                0);
        printf("zeroed region at %p\n", zeroed);
        for (size_t i = 0; i < zeroed_size; ++i) {
            assert(zeroed[i] == 0);
        }
        printf("testing for writability\n");
        ((char *)zeroed)[0] = 1;
        return 0;
    }
    

    char const * 对于测试,实际上这是 void const * .

    赞成的意见

    • 保证区域不可写(生成 SIGSEGV )
    • 不需要memset步骤(检查 mmap(2)

    欺骗

    • 特定于Unix/Linux(自Linux 2.4以来的匿名映射)