#Manual C malloc/realloc/free 'safety enforcer'

42 messages · Page 1 of 1 (latest)

gaunt flame
#

Hi all, I wrote the following functions to help catch memory issues in my software (as there were a few I simply could not find but knew were there), its working great and I caught some stuff with it, but I am wondering if there are any obvious improvements I could do to it to improve its error catching capability.

Regarding test_magic, the idea is that funciton is called in a loop (e.g. renderloop) and if stats is set to true it prints out all pointers currently assigned and their initialization location

heavy ocean
#

I would not allocate so much on the stack. You’re declaring 999,999 of those structs on the stack, which are likely 32 bytes large each. That’s a lot

gaunt flame
#

thats still only 32 mbs so shouldn't be thatt terrible

#

unless it has other implications

#

plus, its a debug only thingy

#

thanks for the info though !

blazing isle
#

what's the magic value for?

gaunt flame
#

If its detected as changed there was a buffer overflow for that pointer

#

it just a guard for looping code that walks down a pointer in increments going over the limit

quartz pebble
#

what's the problem aimed to be solved actually? I didn't get it from the code

gaunt flame
#

its kind of what asan does

#

the idea is to catch instances where

  1. free was called on the same pointer twice
  2. pointer allocated with malloc was read outside of allocated memory
  3. Maintain a list of currently allocated memory and their locations (to find memory that failed to be free()d, i.e. avoid memory leaks)
#

I wrote this when I discovered that the bookkeeping for malloc() was being messed up, likely due to double free() ing a pointer (which turned out to be the case in fact)

gaunt flame
#

here is how the output looks like (if set to show output)

upbeat idol
#

I assume this is not thread safe in any way?

gaunt flame
#

I wouldn't know, did not build it for thread safety

#

It shouldn't be, since they all write into a shared static buffer

#

I guess I could make a lock system if need be

upbeat idol
#

Also, please stop using int for everything. Most of the size value parameters are size_t, you're just implicitly casting back and forth between int and size_t all over the place. You lose both range and some performance that way.

upbeat idol
gaunt flame
#

thanks for letting me know !

#

Whats curious is that gcc with Wall and Wextra does not complain about implicit casting between int and size_t while visual studio does

upbeat idol
#

Just read man pages whenever you use any C or POSIX API. man malloc and you see the exact types

#

compilers don't complain nearly as much as they should imho

#

gcc -Wconversion

gaunt flame
#

Thank you !

#

this will help out a lot

upbeat idol
#

no problem

quartz pebble
# upbeat idol compilers don't complain nearly as much as they should imho

are there crazy people that wrap all primitive inside structures and provide bi-functions operators instead of the regular ones:

typedef struct
{
  unsigned int value;
} UnsignedInt;

inline UnsignedInt unsigned_int_add(const UnsignedInt a, const UnsignedInt b) {
  return { b.value + a.value };
}

// Don't mind this if it doesn't work exactly, it was more for the example
#define add(a,b) _Generic((a)+(b),     \
  unsigned int: unsigned_int_add(a,b)  \
)

so that you're sure you cannot implicitly cast; and then with a macro #if-else game, it could become back

typedef unsigned int UnsignedInt;
#define add(a,b) ((a)+(b))
#

I know Hanson's book provide some example of correct arithmetic interfaces around C built-in primitives ; maybe it's the same kind of idea

upbeat idol
gaunt flame
#

But I don't really want to replace all my + with add()

#

so I'm sticking with test_magic 👍

quartz pebble
#

I started that process for my app (but frst went with "business type" first (typically numbers that have a "physical" unit)), to not mix them together. however, going a step further is kind of appealing

gaunt flame
#

At that point I might just consider using WSL for Asan and valgrind haha

gaunt flame
#

I believe the free_safe should be thread safe assuming that all references to the pointer being freed only exist in the thread