0

I have this piece of code

#define MZERO(a, s)  (a==NULL ? NULL : memset(a, 0, sizeof(a)*s))
#define MALLOC(t)    (t*)malloc(sizeof(t))
#define CALLOC(t, s) s<=0 ? NULL : (t*)MZERO(calloc(sizeof(t), s), s)

which basicaly lets me get around the ridiculous amount of boilerplate C requires for malloc et al. MALLOC and MZERO run as intended however at runtime CALLOC causes

malloc.c:3096: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *)
&((av)->bins[((1) - 1) * 2]))- __builtin_offsetof (struct malloc_chunk, fd)))) &&
old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof
(struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 *
(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end &
pagemask) == 0)' failed.

I've been using these macros in their "simple" format, like MALLOC, and recently decided to combine them. Note that the same error appears even without the triadic operator.

The only references to that error message I've found are some mailing list posts which don't contain a solution. I think I've combined them in the past without any problems but I'm not really sure. In any case my libgc version is 2.13-38+deb7u1 with GCC 4.7.2

Any idea what's going on?

rath
  • 3,655
  • 1
  • 40
  • 53
  • You need more parentheses in the CALLOC macro for safety: `#define CALLOC(t, s) (s<=0 ? NULL : (t*)MZERO(calloc(sizeof(t), s), s))`, adding a set of parentheses around the whole expression. I'd be happier with parentheses around the appearances of `s`. For example, `CALLOC(int, x&0x7)` would be misinterpreted because of the lack of parentheses around the `s` in `s<=0`. Where `s` is used as an argument, I think you're OK, but where it is used in an expression, you are not. – Jonathan Leffler Mar 30 '14 at 19:21
  • @JonathanLeffler You make a valid point although I don't think I'd ever use an expression like this... Parentheses added anyway. Cheers – rath Mar 30 '14 at 19:25
  • `#define MALLOC(t) (t*)malloc(sizeof(t))` , lol – M.M Mar 30 '14 at 20:47
  • @MattMcNabb is that a good lol or should I be worried? – rath Mar 30 '14 at 20:54
  • The `(t*)` bit is a waste of space .. you are worried about "ridiculous boilerplate" but it is of your own devising. Just go `Foo *foo = malloc( sizeof *foo );` – M.M Mar 30 '14 at 20:56
  • @MattMcNabb gcc used to complain if I didn't do the typecast, but then again I've never tried the other way. I also assume you would've told me eventually even if I hadn't prompted you ;) – rath Mar 30 '14 at 21:01
  • If it complains, then fix by doing `#include ` – M.M Mar 30 '14 at 21:02

2 Answers2

1

Yes, such asserts message would appear when the program has some memory corruption scenario. You may want to use Valgrind. Your CALLOC MACRO is also not correct in the sense it is actually clearing memory twice so it should be

#define CALLOC(t, s) s<=0 ? NULL : (t*)MZERO(calloc(sizeof(t), s), s)

should be

   #define CALLOC(t, s) s<=0 ? NULL : (t*)calloc(sizeof(*t), s)
Mantosh Kumar
  • 5,659
  • 3
  • 24
  • 48
  • I always thought calloc simply called malloc in the background, never realized it also initialized memory, so +1 on that. I did as you suggest and placed MZERO around malloc instead. Everything works fine. – rath Mar 30 '14 at 19:21
1

Basically, don't use macros like this. You're just entering a world of pain.

Remember macros are a text expansion performed by the pre-processor. Let's pretend we're the pre-processor, with two of your macros...

#define MZERO(a, s)  (a==NULL ? NULL : memset(a, 0, sizeof(a)*s))
#define CALLOC(t, s) s<=0 ? NULL : (t*)MZERO(calloc(sizeof(t), s), s)

Now, the part MZERO(calloc(sizeof(t), s), s) will expand like this:-

(calloc(sizeof(t), s)==NULL ? NULL : memset(calloc(sizeof(t), s), 0, sizeof(calloc(sizeof(t), s))*s))

I think you didn't really want calloc called three times. I can list a slew of other potential issues because you aren't correctly wrapping each param in brackets within the macros, but really, enough: Don't abuse macros like this.

Roddy
  • 66,617
  • 42
  • 165
  • 277