单头竞技场分配器。 C89兼容。
arena.h的修改竞技场分配者是一种简单的方法,可以通过允许作为一个小组释放多个分配来实现更容易,更快,更安全的动态内存管理。这是通过在大区域中分配内存,然后根据需要分配该内存的部分来完成,从而减少了malloc调用的量(与简单的指针算术相比,这很慢)。
当您摧毁竞技场时,您还可以释放它及其所有内容,减少也很慢的free通话量。再进一步,您可以通过简单地将其内存指针重置为0来清除竞技场,从而使您重复使用它们并消除对更多malloc和free的需求。
您可以通过阅读这篇精彩的文章来了解有关竞技场/区域/地区分配者的更多信息。
我会简短。我维护C89的乐趣合规性,不是因为我使用它。我个人是C11享受者。如果您认为C89是唯一的方法,那么对您有好处!但是你错了。
每当我与其他程序员共享此项目时,我收到的最常见响应之一就是类似的内容:您绝对不应将实现/逻辑代码放在标题文件中!我对此声明进行质疑,原因有三个...
它表明,在教育系统中仍在执行过时的和有害结构,这是通常引入所述结构的地方。
发表此陈述的人很少有相信它的实际原因。这个人是否曾经考虑过为什么他们应该“永远不要将实施/逻辑代码放在标题文件中”?简单地反思他们听到的内容而没有任何依据,他们为什么选择同意它并没有任何帮助,而这个人不应该期望我像他们那样接受它。
最大,最有效的批评是仅标头/单头库,是对标头的更改需要重新编译所有包含它的文件。就我的项目而言,更改arena.h ,即使实际实现仅包含在#define the ARENA_IMPLEMENTATION宏的翻译单元中,也会导致重建所有包含IT的文件。解决方案?一旦arena.h处于所需状态,请停止更改!
链接缓慢而复杂。许多初学者经常在学习链接过程方面遇到困难,而在编写不安全的代码方面,它们也是最大的罪魁祸首。仅此一项就足以使我将这个竞技场分配给一个仅标题的图书馆。我的代码(当前状态)非常小,大约300行。当您可以简单地#include一次并开始使用它时,为什么要让您构建并链接如此小的实现?如果您确实有问题,则单头格式的分配器不会阻止您遵循源+标头构造,如果您愿意的话。哎呀,请随时分叉并制作源+标题,它是有原因的开源!
这不会实现内核级别的分配器,而是包装malloc和free (标准库或自定义,您的选择)。
尽管我确实认为软件应该是开源的,但我认为需要使用此库也是开源的软件是道德的。在现代技术和世界当前状态中,编写记忆安全代码比以往任何时候都重要。因此,该软件是根据Apache许可证版本2.0许可的。如果您考虑使用该软件,则强烈建议您阅读LICENSE (以下内容,在arena.h中,及其自己的文件),除非您认为您100%熟悉条款和条件。
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Copyright 2024 Carter Dugan
竞技场分配器的文档都可以在arena.h中找到。标题文件的顶部有评论,并提供快速说明以便您的方便。
对于一个翻译单元中的一个文件,您需要以下内容:
#define ARENA_IMPLEMENTATION
#include "arena.h"从那时起,其他翻译单元中的其他文件通常可以简单地#include "arena.h" 。您可以定义/使用其他宏。请参阅有关功能和宏的部分。
arena.h中定义了两个结构。这列出了每个人及其成员。
Arena_Allocation Arena分配的数据结构。仅在定义ARENA_DEBUG时可用。
size_t index分配开始的竞技场中的索引。size_t size的内存大小分配给该字节中的此分配。char *pointer分配关联的指针。struct Arena_Allocation_s *next链接列表中的下一个分配。竞技场的Arena数据结构。
char *region分配的内存区域。size_t index要分发下一个指针的区域索引。size_t size的内存大小分配给字节中的竞技场。unsigned long allocations已经进行了竞技场分配的数量。仅在定义ARENA_DEBUG时可用。Arena_Allocation *head_allocation竞技场中进行的第一个分配(用于链接列表)。仅在定义ARENA_DEBUG时可用。 /*
Allocate and return a pointer to memory to the arena
with a region with the specified size. Providing a
size of zero results in a failure.
Parameters:
size_t size | The size (in bytes) of the arena
memory region.
Return:
Pointer to arena on success, NULL on failure
*/
Arena * arena_create ( size_t size );
/*
Return a pointer to a portion of specified size of the
specified arena's region. Nothing will restrict you
from allocating more memory than you specified, so be
mindful of your memory (as you should anyways) or you
will get some hard-to-track bugs. By default, memory is
aligned by alignof(size_t), but you can change this by
#defining ARENA_DEFAULT_ALIGNMENT before #include'ing
arena.h. Providing a size of zero results in a failure.
Parameters:
Arena *arena | The arena of which the pointer
from the region will be
distributed
size_t size | The size (in bytes) of
allocated memory planned to be
used.
Return:
Pointer to arena region segment on success, NULL on
failure.
*/
ARENA_INLINE void * arena_alloc ( Arena * arena , size_t size );
/*
Same as arena_alloc, except you can specify a memory
alignment for allocations.
Return a pointer to a portion of specified size of the
specified arena's region. Nothing will restrict you
from allocating more memory than you specified, so be
mindful of your memory (as you should anyways) or you
will get some hard-to-track bugs. Providing a size of
zero results in a failure.
Parameters:
Arena *arena | The arena of which the pointer
from the region will be
distributed
size_t size | The size (in bytes) of
allocated memory planned to be
used.
unsigned int alignment | Alignment (in bytes) for each
memory allocation.
Return:
Pointer to arena region segment on success, NULL on
failure.
*/
void * arena_alloc_aligned ( Arena * arena , size_t size , unsigned int alignment );
/*
Copy the memory contents of one arena to another.
Parameters:
Arena *src | The arena being copied, the source.
Arena *dest | The arena being copied to. Must be created/allocated
already.
Return:
Number of bytes copied.
*/
ARENA_INLINE size_t arena_copy ( Arena * dest , Arena * src );
/*
Reset the pointer to the arena region to the beginning
of the allocation. Allows reuse of the memory without
realloc or frees.
Parameters:
Arena *arena | The arena to be cleared.
*/
ARENA_INLINE void arena_clear ( Arena * arena );
/*
Free the memory allocated for the entire arena region.
Parameters:
Arena *arena | The arena to be destroyed.
*/
ARENA_INLINE void arena_destroy ( Arena * arena );
/*
Returns a pointer to the allocation struct associated
with a pointer to a segment in the specified arena's
region.
Parameters:
Arena *arena | The arena whose region should
have a portion pointed to by
ptr.
void *ptr | The ptr being searched for
within the arena in order to
find an allocation struct
associated with it.
*/
Arena_Allocation * arena_get_allocation_struct ( Arena * arena , void * ptr );
/*
Adds an arena allocation to the arena's linked list of
allocations under debug.
Parameters:
Arena *arena | The arena whose allocation list
should be added to
size_t size | The size of the allocation being
added.
*/
void arena_add_allocation ( Arena * arena , size_t size );
/*
Deletes the arena's linked list of allocations under
debug.
Parameters:
Arena *arena | The arena whose allocation list
is being deleted.
*/
void arena_delete_allocation_list ( Arena * arena );在代码中,您可以定义一些可选的宏。 ARENA_MALLOC , ARENA_FREE和ARENA_MEMCPY可以分别分别分配给替代的malloc , free -like -like和memcpy -like功能,并且arena.h将使用它们代替标准库功能。您可以通过定义ARENA_DEBUG来访问其他调试功能,以跟踪分配。最后,您还可以通过定义ARENA_DEFAULT_ALIGNMENT值来指定分配对齐的默认值。请参阅下面的示例。
// All of these are optional
// Replace standard library functions
#define ARENA_MALLOC <stdlib_malloc_like_allocator>
#define ARENA_FREE <stdlib_free_like_deallocator>
#define ARENA_MEMCPY <stdlib_memcpy_like_copier>
// for debug functionality:
#define ARENA_DEBUG
// If you would like to change the default alignment for
// allocations:
#define ARENA_DEFAULT_ALIGNMENT <alignment_value>还有一个用于确定类型对齐的宏。像其他所有内容一样,它也对C89友好,尽管在C11下进行编译时,它将使用stdalign.h的alignof 。
ARENA_ALIGNOF ( type ) // Gives alignment of `type` 该代码的编写是为支持C89标准并在任何平台上运行的任何编译器构建。但是,用Makefile在窗户上构建有一些问题。请阅读以下所有信息。
测试和示例已在以下编译器和版本下进行编译并成功运行:
测试和示例已编译并成功地在以下操作系统上运行:
请注意$ make test由于使用Valgrind和.exe扩展名,当前尚未将MakeFile配置为在Windows上工作。这应该是一个简单的修复程序,并在我的待办事项列表中(随时打开问题并自己解决此问题!)。
该项目具有非常简单的贡献指南。
对于arena.h代码的任何贡献,请仅在解决问题请求或修复错误的问题时才打开“拉请请求”。遵循代码样式并在打开拉动请求之前运行自动测试。所有测试必须通过。
对于功能请求或错误,请打开问题。然后,您可以自己解决这个问题。
对于其他任何事情,请打开一个问题,我们将讨论它。
arena.h目前,没有关于代码样式的文档,但是应该相对简单,可以通过在大多数情况下读取现有代码来进行拾取。如果您遇到麻烦,请随时为FR打开问题。如果已经存在,请对其进行评论,以描述您被混淆的内容。
如果您修改arena.h ,则必须运行测试。请参阅下一节。
如果您在arena.h中添加功能,则必须在test.c中创建足够的测试或测试。
如果您在arena.h中添加功能,则必须在code_examples/添加足够的示例,并将其添加到makefile中,但不需要。
如果您更改arena.h ,请在打开PR之前进行测试。如果您打开对代码进行修改的PR,并且测试并非全部通过,请对您的PR发表评论,说明您认为哪种测试是错误的,并阻止您通过所有测试。如果任何测试失败,并且您的公关没有评论声称要纠正失败测试的评论,则您的公关将被忽略。
除了解决错误和功能请求之外,还可以在arena.h内完成功能请求或错误修复功能。H允许在test.c中修改或添加相关的测试代码。C,如果您希望确认PR,则必须这样做。在test.c中以注释的形式在test.c中进行测试代码的文档。
测试还必须通过无阀泄漏, arena.h必须符合C89。您应该使用Makefile检查此内容,但是如果出于某种原因您不能或不想检查此信息,请与test.c一起编译。
-Werror -Wall -Wextra -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Wdeclaration-after-statement
并且为了合规,请汇编test_compliance.c
-pedantic -std=c89 -Werror -Wall -Wextra -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Wdeclaration-after-statement
就像我说的那样,您可以用Makefile来完成所有这些
$ make test
标识符
variable_name 。对于指针,星号( * )应附加到变量名称,而不是类型,例如type *variable_name 。type function_name(p1, p2, ...) 。对于指针,应将星号( * )附加到密度的类型上,例如type* function_name(p1, p2, ...) 。函数应具有正向声明,并在文件顶部的顶部上方进行注释,以确保相对于其他功能的订单是一致的。struct StructName 。它们应被打字并位于标头文件的顶部。ARENA_开始,例如ARENA_MACRO_NAME 。请避免在不咨询我的情况下添加宏。但是,请随时更改现有宏。白空间基于与周围的代码行的相关性。如果您不了解这些要点是什么意思,请查看代码。它的格式应如下:
应尽可能进行错误检查,并模仿标准库实现的行为,例如返回返回指针的函数中的NULL或从整数函数返回整数错误值。您应该使用早期错误检查,这意味着要尽快检查错误,例如。检查失败的malloc呼叫后返回的NULL 。
评论应该描述您为什么做某事,而不是您做的事情。换句话说,您的代码应该是不言自明的。以注释形式进行功能的文档应以以下格式位于函数上方:
/*
Description of function, description of function description of function.
Description of function description of function, description of function
description of function.
Parameters:
paramter1_type paramter1_name | Description of parameter 1, description
of parameter one description of paramter
1.
paramter2_type paramter2_name | Description of parameter 2, description
of parameter one description of paramter
2.
Return:
Description of return value, description of return value description of return value.
*/