2

I have a C program like the one below. I am trying to write a wrapper on top of malloc with the signature int myAlloc(). This wrapper should return 1 on a successful memory allocation or return 0 if memory allocation fails.

#include <stdio.h>
#include <stdlib.h>

int myAlloc(void **ptr, int size)
{
    *ptr = malloc(size);

    if (!ptr)
        return 0;
    else
        return 1;
}

void main()
{
    int *p = NULL;
    myAlloc(&p, sizeof(int));
    printf("%d\n", *p);
}

When I compile this I get a warning saying "incompatible pointer type". How can I make it possible for this function to be called with any possible pointer type without receiving the warning?

Is it possible to remove the casting operation from the actual function call?

Update

I found the answer. Here is corrected code:

#include <stdio.h>
#include <stdlib.h>

int myAlloc(void *ptr,int size)
{
    *(void **)ptr = malloc(size);

    if (!ptr)
        return 0;
    else
        return 1;

}

int main()
{
    int *p = NULL;
    myAlloc(&p, sizeof(int));
    *p = 5;
    printf("%d\n", *p);

    return 1;
}
Community
  • 1
  • 1
user995487
  • 141
  • 2
  • 2
  • 9
  • This appears to not be standard c, or C++, as main does not return void. – Richard J. Ross III Mar 23 '12 at 13:30
  • @RichardJ.RossIII You are wrong. Read [this](http://stackoverflow.com/questions/5296163/why-is-the-type-of-the-main-function-in-c-and-c-left-to-the-user-to-define/5296593#5296593). – Lundin Mar 23 '12 at 13:31
  • 1
    @Lundin I have read that, and my point still stands. I don't believe that this is in a freestanding environment, or hosted environment. – Richard J. Ross III Mar 23 '12 at 13:33
  • 4
    @Ludin that link clearly states that main should return `int`. But this is beside the point – thecoshman Mar 23 '12 at 13:34
  • @Richard, I think you mean you don't think it's freestanding, since it has to be one or the other. Hosted is what most people use, Linux, Windows, etc, freestanding is embedded, Linux kernel and so on. Nothing in the code or question seems to mandate that it's hosted but you're probably right. – paxdiablo Mar 23 '12 at 13:37
  • @RichardJ.RossIII You don't think this is freestanding _or_ hosted?? All programs ever written falls in either of those two categories. – Lundin Mar 23 '12 at 13:38
  • @thecoshman No it doesn't. Read it. Nothing in this post indicates whether this code is hosted or freestanding. – Lundin Mar 23 '12 at 13:39
  • 2
    @Lundin: It is conventional to assume that posted C code is intended for use in a hosted environment as it is by far the more comment environment and in addition it is far more completely specified. If you think that the code is for a freestanding environment then you could claim that the entry point shouldn't be `main` or there shouldn't be one which is of little help to anyone. If the intended target is a hosted environment then `main` _must_ be defined with a return type of `int`. – CB Bailey Mar 23 '12 at 13:44
  • Basically, it is undetermined whether the OP's program is hosted or freestanding. But `void main()` is just silly. And wrong: it should **at least** be be `void main(void)`. OTOH: if it were a freestanding app, the OP wouldn't have asked the question in the first place ... – wildplasser Mar 23 '12 at 13:44
  • 4
    you should `if(!*ptr) return 0;`. note: would you guys please stop arguing about `main()`? :) – Karoly Horvath Mar 23 '12 at 14:04
  • 1
    @wildplasser: `void main()` and `void main(void)` are only different in declarations which are not part of a definition – Christoph Mar 23 '12 at 15:09

9 Answers9

4

your function, myMalloc takes a pointer to a pointer to void, or void** you are passing it the address of a pointer to an int, or int**

You need to cast the pointer you pass to be void eg

myAlloc((void**)&p,sizeof(int));
thecoshman
  • 8,394
  • 8
  • 55
  • 77
  • yes this would solve. But Is it possible to remove the casting operation away from the actual function call ? – user995487 Mar 23 '12 at 14:57
  • this results in undefined behaviour due to violating strict aliasing at `*ptr=malloc(size)` (C99 6.5 §7) – Christoph Mar 23 '12 at 15:34
  • 1
    I don't think so... templates would make it a doddle, but IIRC C has nothing like templates. Other wise, overload for all types, but then that is just going to get messy – thecoshman Mar 23 '12 at 15:35
0

The actual error I see -- which may not be the same as yours; we can't know, since you neglected to show us the actual output -- looks like this:

src.c: In function ‘main’:
src.c:15:17: warning: passing argument 1 of ‘myAlloc’ from incompatible pointer type [enabled by default]
src.c:4:5: note: expected ‘void **’ but argument is of type ‘int **’

You're passing your myAlloc function an int ** variable, but your function is written to accept a void ** variable. You can cast the pointer type in the function call like this:

myAlloc((void **)&p,sizeof(int));

And now it compiles without warnings.

You may want to read the pointers section of The C Book, especially section 5.3.5, which explicitly addresses some of the issues raised here.

larsks
  • 277,717
  • 41
  • 399
  • 399
  • It will not give an warning, but it may crash. think about a platform that has `sizeof(int*) – asaelr Mar 23 '12 at 14:41
  • That's one of the reasons that I pointed at section 5.3.5 of the C book. If you take a look you'll see it discusses this. – larsks Mar 23 '12 at 15:22
0

This may seem interesting academically, but isn't your internal code in the wrapper doing the same type of boolean check?

void *ptr;
if( (ptr = malloc(1000)) )
{
  /* Do stuff with ptr */
}
else
{
  /* throw a tantrum */
}

Do you really need the int return code with the extra parameter complexity?

buzzwang
  • 336
  • 3
  • 3
0

In C, there is a void* type for general pointer, but there is not a type for general pointer to pointer. Even worse, the size of different types of pointers may not be equal. Hence, if your function doesn't know what type of pointer it should assign, it cannot just "put the data in the address", because the size of the right pointer may be different from the size of the pointer it assign.

For example, your code may crash (and is UB) if sizeof(int*)<sizeof(void*).

Because of this, I think that it's impossible to write a wrapper like you want.

asaelr
  • 5,438
  • 1
  • 16
  • 22
0

There's no way to write such a function in standards-compliant C as int * and void * are not compatible types.

A (mostly) equivalent macro definition could look like this:

#define myAlloc(PTR, SIZE) (!!(PTR = malloc(SIZE)))
Christoph
  • 164,997
  • 36
  • 182
  • 240
0
#include <stdio.h>
#include <stdlib.h>

int myAlloc(void *ptr,int size)
{
    *(void **)ptr=malloc(size);
    if(!ptr) return 0;
    else return 1;

}

int main()
{
    int *p=NULL;
    myAlloc(&p,sizeof(int));
    *p=5;
    printf("%d\n",*p);
    return 1;
}
Exikle
  • 1,155
  • 2
  • 18
  • 42
user995487
  • 141
  • 2
  • 2
  • 9
-1

p is type int*, while your function accepts void**.

myAlloc((void **)&p,sizeof(int));
thelaws
  • 7,991
  • 6
  • 35
  • 54
-1

As per the signature of myAlloc, you should call it with myAlloc((void**)&p,sizeof(int)) since p is int* (ptr to int) and not void* (ptr to void).

roberth-k
  • 94
  • 1
  • 2
-2

OT: There is a bug in your code. You probably want:

   if(!(*ptr)) return 0;
Klas Lindbäck
  • 33,105
  • 5
  • 57
  • 82