單頭競技場分配器。 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.
*/