0

I came across int safe_alloc_realloc_n (void *ptrptr, size_t size, size_t count) function, at Github/scratchpadRepos/gnulib, which is actually an older version of the official gnulib,

In that function, I found *(void **)ptrptr weird, With or without the cast, it contains a memory address, so is there any point of casting here,

gitman-2021
  • 111
  • 8
  • 3
    `Also, may i ask` Please one question per question. – KamilCuk Dec 12 '22 at 13:42
  • 1
    for the first question c++ seems to be not relevant because it is c – 463035818_is_not_an_ai Dec 12 '22 at 13:43
  • 1
    And for the second question, no, `malloc` and `new` are not equivalent. `malloc` is just at the halfway of the road, `new` contructs an object while `malloc` doesn't. C and C++ are not the same language, otherwise they wouldn't be two separate languages. – Fareanor Dec 12 '22 at 13:46
  • 1
    https://stackoverflow.com/questions/184537/in-what-cases-do-i-use-malloc-and-or-new – pptaszni Dec 12 '22 at 13:50
  • 1
    `*(void **)ptrptr = NULL` (where `ptrptr` is a `void *`) treats `ptrptr` as the address of a `void *`. Just doing `*ptrptr = NULL` won't work, since `void *` is special - in both C or C++ - and cannot be dereferenced. Also, your usage of `NEW` is not equivalent to operator `new` in C++ - `malloc()` only allocates raw memory, whereas a `new` expression in C++ both allocates raw memory AND (given an appropriate `new` expression) initialises it (e.g. by calling a constructor of a class type) so that memory contains a valid object. – Peter Dec 12 '22 at 13:51
  • My apology, to waste your time, by mentioning cpp, i have updated the answer now – gitman-2021 Dec 12 '22 at 13:52
  • 1
    Dereferencing a `void *` (which is what `*ptrptr` does) is diagnosable error. Dereferencing other pointer types (e.g. `void **`, `int *`, etc) is not a diagnosable error. – Peter Dec 12 '22 at 14:04

1 Answers1

2

Why gnulib uses *(void **) ptrptr instead of proper, and without cast, usage

The argument is a void *, doing *ptrptr would try to assign to void. void is a void, you can't assign to it.

On POSIX systems you can cheat, all pointers have the same alignment and size. You can do int *a; *(void **)&a = some_value;, although such code is very invalid according to C language.

The function takes a generic pointer void * and then assigns to the pointer, so that you can int *a; safe_alloc_realloc_c(&a, ...) pass a pointer to any pointer type. Otherwise you would have to create a separate function for every type safe_alloc_realloc_c_int(int **, ...) safe_alloc_realloc_c_char(char **, ...) etc.

Have same functionality,

No. malloc allocates memory. new allocates the memory and creates an object, calling object constructor and starting object lifetime.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • 2
    Rather, on _Linux_ you can cheat since it relies so deeply on both documented and undocumented non-standard extensions of gcc that it will instantly crumble into pieces if ever compiled with a different compiler. I don't think anything in POSIX as such requires the use of dirty casts. – Lundin Dec 12 '22 at 13:59
  • @Lundin Not just Linux though; basically any combination of (GCC | clang | ICC) + (libc | musl), wherever that may run. And I think Kamil has a point in that POSIX *essentially* requires this behaviour for some of its functions to be usable, IIRC (but I can't think of an example right now; probably something with pthreads). – Konrad Rudolph Dec 12 '22 at 14:04
  • @KonradRudolph There's the dirty hack of casting a value or pointer into a void* for the pthread callback and then cast it back, but that's just abuse of the POSIX API rather than something encouraged by POSIX. – Lundin Dec 12 '22 at 14:15
  • The problems start from the function prototype. Then it is only getting worse. – 0___________ Dec 12 '22 at 14:22
  • 1
    @Lundin Actually I think I misremembered that; I was probably thinking of the function pointer/object pointer equivalence in POSIX (via e.g. `dlsym`) which is undefined in C. – Konrad Rudolph Dec 12 '22 at 14:46
  • Yes— `dlsym()` is a troublemaker. – Jonathan Leffler Dec 12 '22 at 16:05