gpt4 book ai didi

c - 是否可以在 C 中编写符合要求的 malloc 实现?

转载 作者:太空狗 更新时间:2023-10-29 16:39:03 25 4
gpt4 key购买 nike

这是 Can a char array be used with any data type? 的跟进

我知道动态内存和 malloc 的常见实现,可以在 wikipedia 上找到引用资料.我也知道 malloc 返回的指针可以转换为程序员想要的任何东西,甚至没有警告,因为标准在 6.3.2.3 指针 §1

A pointer to void may be converted to or from a pointer to any incomplete or object type. A pointer to any incomplete or object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.

问题是假设我有一个没有 mallocfree 的独立环境,我如何在符合 C 语言的环境中构建这两个函数的实现?

如果我对标准有一些自由,这很容易:

  • 从一个大字符数组开始
  • 使用相当大的对齐方式(对于许多架构,8 个应该足够了)
  • 实现一个算法,从该数组返回地址,在该对齐方式,跟踪已分配的内容 - 很好的例子可以在 malloc implementation? 中找到

问题是该实现返回的指针的有效类型仍然是 char *

标准在同一段§ 7 中说

A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the pointed-to type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer.

这似乎不允许我假装被声明为简单字符的东西可以神奇地包含另一种类型,甚至可以在这个数组的不同部分或同一部分的不同时刻包含不同的类型。不同的是,取消引用此类指针似乎是未定义的行为,具有严格的标准解释。这就是为什么当您在字符串缓冲区中获取对象的字节表示时(例如,当您从网络流中读取它时),常见的习语使用 memcpy 而不是别名。

那么我如何在纯 C 中构建 malloc 的一致实现???

最佳答案

这个答案只是对标准的一个解释,因为我在C99 n1256草案和C11 n1570中都找不到明确的答案。

基本原理来自 C++ 标准(C++14 草案 n4296)。3.8 对象生命周期 [basic.life] 说(强调我的):

§ 1The lifetime of an object of type T begins when:

  • storage with the proper alignment and size for type T is obtained, and
  • if the object has non-vacuous initialization, its initialization is complete.

The lifetime of an object of type T ends when:

  • if T is a class type with a non-trivial destructor (12.4), the destructor call starts, or
  • the storage which the object occupies is reused or released.

§ 3 The properties ascribed to objects throughout this International Standard apply for a given object onlyduring its lifetime.

我知道C和C++是不同的语言,但是它们是有联系的,上面只是在这里解释下面的解释

C标准中的相关部分是7.20.3内存管理函数。

... The pointer returned if the allocationsucceeds is suitably aligned so that it may be assigned to a pointer to any type of objectand then used to access such an object or an array of such objects in the space allocated(until the space is explicitly deallocated). The lifetime of an allocated object extendsfrom the allocation until the deallocation. Each such allocation shall yield a pointer to anobject disjoint from any other object. The pointer returned points to the start (lowest byteaddress) of the allocated space...

我的解释是,如果你有一个大小和对齐正确的内存区域,例如一个大字符数组的一部分,但是任何其他类型的数组类型都可以在这里使用,你可以假装它是指向未初始化的对象或另一种类型的数组(比如 T),并将指向区域第一个字节的 char 或 void 指针转换为新类型 (T) 的指针。但是为了不违反严格的别名规则,这个区域不能再通过任何以前的值或指针或初始类型访问 - 如果初始类型是字符,它仍然允许读取,但写入可能会导致陷阱表示。由于此对象未初始化,它可以包含陷阱表示并在其初始化之前读取它是未定义的行为。此 T 对象及其关联的指针将一直有效,直到您决定将内存区域用于任何其他用途并且此时指向 T 的指针变为悬空。

TL/DR:严格的别名规则只要求一个内存区域在一个时刻只能包含一个有效类型的对象。但是您可以为提供的不同类型的对象重新使用内存区域:

  • 尺寸和对齐方式兼容
  • 在使用前用正确的值初始化新对象
  • 您不再访问初始对象

因为这样您就可以简单地将内存区域用作分配的内存。

根据 C 标准,初始对象的生命周期不会结束(静态对象会持续到程序结束,而自动对象会持续到其声明范围结束),但是您不能再访问它,因为严格的别名规则

关于c - 是否可以在 C 中编写符合要求的 malloc 实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38515179/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com