1
 int test_malloc(void **ptr, size_t size)
 {
    (*ptr) = malloc(size);
    return 0;
 }

 int test_app()
 {
   char *data = NULL;
   int ret = 0;
   ret = test_malloc((void **)&data, 100);
 }

Compiler: gcc 4.1.2

Among others, I am using -O2 & -Wall which are I think are turning on some options which checks for this.

Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
Jay
  • 24,173
  • 25
  • 93
  • 141
  • possible duplicate of [Dereferencing type-punned pointer will break strict-aliasing rules](http://stackoverflow.com/questions/3246228/dereferencing-type-punned-pointer-will-break-strict-aliasing-rules) – Richard J. Ross III May 10 '12 at 06:02
  • Also, don't write interfaces such as `test_app`. It is supposed to return an `int` and you don't return one, and to receive an unspecific number of arguments where it doesn't receive any. gcc should have told you for the return value. – Jens Gustedt May 10 '12 at 06:24

3 Answers3

3

You have a variable of type char*, and in test_malloc you are modifying it through an lvalue of type void *, which breaks strict aliasing rules.

You could solve it like this:

 int test_app()
 {
   char *data = NULL;
   void *void_data = NULL;
   int ret = 0;
   ret = test_malloc(&void_data, 100);
   data = (char*)void_data;
 }

But even better is to make test_malloc return void* to avoid problems like this.

Timo
  • 5,125
  • 3
  • 23
  • 29
2

You cannot do what you're trying to do in C; it's invalid code. If you want to use void * to return generic pointers, the only way to do so is the return value. This is because void * converts to any pointer type, and any pointer type converts to void *, but void ** does not convert to a pointer to some other type of pointer, nor do pointers to other pointer types convert to void **.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • And I forget: does the standard even guarantee that `char*` and `void*` have the same object representation? Supposing the representations were different, then even if the conversion were allowed and didn't get trashed by the optimizer because of the strict aliasing violation, the code certainly wouldn't work since reinterpreting the `void*` written by `test_malloc` as a `char*` would give the wrong address. – Steve Jessop May 10 '12 at 09:05
  • Actually I believe they are required to have the same representation because `void *` is essentially specified as a copy of `char *` with extra automatic conversions but no dereferencing or arithmetic. Might want to check to be sure though. I think it's still an aliasing violation to access it that way, though. – R.. GitHub STOP HELPING ICE May 10 '12 at 13:58
  • Yes, I agree that the aliasing violation is already a show-stopper. I was trying to pile on motivations for that. Not that GCC actually does use different representations for different object pointer types anywhere AFAIK, but the standard allows for peculiar architectures. If it wasn't `char*` but `int*` then there might even be a historical example. – Steve Jessop May 10 '12 at 14:03
1

I try like this one works fine

void * test_malloc(int size)
{
    void *mem = malloc(size);
    if (mem == NULL)
    {
        printf("ERROR: test_malloc %d\n", size);
    }
    return mem;
}

 int test_app()
 {
   char *data;
   int ret = 0;
   data = test_malloc(100);

   if(data != NULL)
         free(data);
 }
Oki Sallata
  • 374
  • 1
  • 10