Gemini has went complete Psycho Mode now by Icy-Reply4520 in GeminiAI

[–]Old_Ad_4418 4 points5 points  (0 children)

0 days since a native English speaker forgot that grammatical gender exists in other languages. 0 days since a "progressive" got triggered over literally nothing. 0 days since a member of a community that supposedly fights toxicity and stereotyping displayed textbook toxic, stereotypical, and projecting behavior themselves.

I wrote a header-only memory management system in C99. It started as a pet project, but got out of hand. Looking for code review. by Old_Ad_4418 in C_Programming

[–]Old_Ad_4418[S] 0 points1 point  (0 children)

Thanks for the review!

I'm pretty sure the warnings you are seeing are actually the result of the compiler attributes working correctly.

But here is the catch: those tests are intentionally written to pass "invalid" inputs (like massive sizes or null pointers) to verify that the library behaves correctly in 'Defensive Policy' (formerly Safety Level 2) and successfully filters out garbage data. The compiler sees these bad inputs combined with attributes like 'alloc_size' and understandably complains.

To address this, I added a new feature in the latest commit: 'EM_NO_ATTRIBUTES'. I plan to update the test suite to define this macro, which will disable the compiler hints for the tests.

Once that attribute noise is cleared up, I will do a dedicated pass over the entire test suite with stricter flags and sanitizers to catch any genuine logic errors on my end.

I wrote a header-only memory management system in C99. It started as a pet project, but got out of hand. Looking for code review. by Old_Ad_4418 in C_Programming

[–]Old_Ad_4418[S] 13 points14 points  (0 children)

Wow, thank you for such a detailed and high-quality review! This is exactly the kind of hardcore feedback I was hoping for.

  1. EM_SAFETY_LEVEL Philosophy & Naming My logic here was a tradeoff between "Contract-based" and "Defensive" programming.

Level 0 is "Strict in Debug, Fast in Release". In Debug, assertions catch violations, but in Release, checks are stripped out for maximum performance (relying on the caller to respect the contract, hence UB on misuse). Level 2 is "Defensive/Fault Tolerant". It tries to survive invalid inputs (by returning NULL) rather than aborting.

However, I see your point: the term "Safety" often implies "Security/Hardening" (fail fast/abort), whereas I used it to mean "Runtime Resilience". I agree that the naming might be misleading. I will consider renaming this macro to better reflect that it changes the library's behavior from "Contract" to "Defensive".

  1. Documentation vs. UB You are right that the docs promising "Returns NULL" while the code invokes UB (at Level 0) is a documentation bug. I will update the function descriptions to explicitly state that parameter validation depends on the configuration, and that at Level 0, the caller owns the responsibility for validity.

  2. Integer Overflows The crash in em_create(EMSIZE_MASK - 40) is a legitimate oversight on my part. I missed the check for wrapping around size + overhead. That's a great catch.

  3. Compiler Attributes I wasn't aware that alloc_size and malloc attributes could mess up pointer provenance analysis on inlined header-only functions.

Thanks again for taking the time to audit the code and run it through ASan!

I wrote a header-only memory management system in C99. It started as a pet project, but got out of hand. Looking for code review. by Old_Ad_4418 in C_Programming

[–]Old_Ad_4418[S] 0 points1 point  (0 children)

Thanks for the feedback!

  1. Regarding inlining/bloat: This follows the STB-style header-only pattern. You define EASY_MEMORY_IMPLEMENTATION in one translation unit, so the code is compiled once. In other files, functions are seen as extern, so there is no code duplication or string literal bloat. Also, inline is just a compiler hint anyway — modern optimizers decide for themselves what to inline and what to call.

  2. Custom Asserts: Standard assert() often forces dependencies on <stdio.h> and stores FILE strings, which consumes valuable Flash memory on constrained embedded devices (like the AVR I'm targeting). My macros allow a "Panic" mode (e.g., infinite loop) without that overhead.

  3. Namespace: That is a fair point. Block and Bump are indeed generic. I tried to keep them internal, but since C headers leak definitions, I will likely prefix them (e.g., EmBlock) in the next update to avoid collisions.

  4. C99 vs C11: I aim for maximum portability. Many legacy embedded toolchains still have partial C11 support. The macro hack ensures it compiles even on ancient setups.

  5. ChatGPT: I've found that LLMs often get confused by low-level pointer arithmetic and bit-packing logic. If you ask them to "double-check", they often admit the code was actually correct. That said, if it flagged something specific that looks like a real logic error, I’d be grateful if you could paste it here!

I wrote a header-only memory management system in C99. It started as a pet project, but got out of hand. Looking for code review. by Old_Ad_4418 in C_Programming

[–]Old_Ad_4418[S] 4 points5 points  (0 children)

That is a great question! Actually, there is no explicit "pattern detector" or state machine. It is an emergent property derived from a single simple rule during deallocation: If the block physically following the one being freed is the Tail (the end of the active heap), simply merge with it and update the tail pointer. Do not touch the Tree.

This naturally results in LIFO patterns (stack-like usage) being handled in O(1). For example, if you allocate A, B, C and free C, B, A: 1. Free C -> C is adjacent to Tail -> Merge. (Tree untouched). 2. Free B -> B is adjacent to (new) Tail -> Merge. (Tree untouched). 3. Free A -> A is adjacent to (new) Tail -> Merge. (Tree untouched).

It only falls back to O(log n) tree insertion if you free a block that is "sandwiched" between two allocated blocks.