TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

A simple, arena-backed, generic dynamic array for C

86 pointsby david2ndaccountover 1 year ago

7 comments

habiburover 1 year ago
And if you are not using arena -- realloc() is your best bet. And no, it won&#x27;t move your memory around into larger areas every time you call it. Most of the time it will simply bump up the allocation end point. This happens more frequently than you think.<p>In my code I don&#x27;t use allocated_length and used_length seperately in dynamic vectors. Simply realloc() every time one element is added. No measurable difference in speed, and code is much more clean.
评论 #37791367 未加载
评论 #37789360 未加载
评论 #37790687 未加载
评论 #37789853 未加载
评论 #37790633 未加载
评论 #37789272 未加载
asicspover 1 year ago
See also: An easy-to-implement, arena-friendly hash map <a href="https:&#x2F;&#x2F;nullprogram.com&#x2F;blog&#x2F;2023&#x2F;09&#x2F;30&#x2F;" rel="nofollow noreferrer">https:&#x2F;&#x2F;nullprogram.com&#x2F;blog&#x2F;2023&#x2F;09&#x2F;30&#x2F;</a><p>Discussion: <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=37720976">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=37720976</a>
fovcover 1 year ago
What’s the difference between this and other dynamic array implementations? I thought they were all data&#x2F;length&#x2F;capacity headers with exponential resizing.<p>I know when using realloc the old buffer is recycled unlike with this arena, but that seems like more of an arena vs. Malloc distinction, no?<p>In contrast the hash map discussion was more interesting to me because it’s a different data structure that’s explicitly arena friendly
fovcover 1 year ago
&gt; On average they consume about twice the memory of a fixed array of the same size.<p>Not to split hairs, but that’s just the “unfreed” memory overhead.<p>If you have 2^n+1 elements, you’ve provisioned 2^(n+1) slots and leaked ~2^(n+1) on top, making the actual overhead there closer to 4x.<p>I think that means the average overhead is more like 3x (sometimes 4x, sometimes 2x).
yobertzover 1 year ago
I think I would make grow() like this to prevent the mistake of accidentally laying out the array fields in the wrong order.<p><pre><code> void grow(void **ptr, ptrdiff_t *cap, ptrdiff_t *len, arena *a) ... #define push(s, a) ... grow((void **)&amp;s-&gt;data, &amp;s-&gt;cap, &amp;s-&gt;len)</code></pre>
评论 #37792968 未加载
jstimpfleover 1 year ago
The memcpy() from the &quot;specific&quot; slice to the &quot;generic&quot; slice in <i>grow()</i> is technically UB I think. Those slice structures are not the same types.<p>Furthermore, a void pointer can be implemented &quot;differently&quot; than a typed pointer. The size of pointers can (theoretically) be different for different types. Any typed pointer roundtrips safely to a void pointer and back, but the inverse doesn&#x27;t necessarily hold.<p>Then again, not sure which implementations might make problems here. For example, keeping a typed version of a void pointer returned by malloc() and using it to free() later is common practice.
评论 #37789307 未加载
评论 #37789300 未加载
maccardover 1 year ago
I appreciate the simplicity of this, and it&#x27;s a great way to learn how memory management works under the hood. It&#x27;s also a fun series.<p>That said, everything in this article is why I prefer C++ to C. All of the scoping is automatic, you get actual type safety, you remove a whole class of bugs around passing in the wrong arena.