pass a pointer-to-pointer, or return a pointer?

If one wants to get a start address of a array or a string or a block of memory via a function, there are at least two methods to achieve it:
(1) one is to pass a pointer-to-pointer parameter, like:

int my_malloc(int size, char **pmem)
{
      *pmem=(char *)malloc(size);
      if(*pmem==NULL) {
             return NOK;
      }
      return OK;
}
int main()
{
       char *my_pmem;
       if(my_malloc(64, &my_pmem)==OK){
        ...
       } else {
       ...
       }
}

(2)the other is to return a pointer, like:

void * my_malloc(int size)
{
       void * pmem;
       pmem=malloc(size);
       return pmem;
}
int main()
{
      char *my_pmem;
      my_pmem=(char *)my_malloc(64);
      if(my_pmem==NULL) {
           ...
      } else {
           ...
      }
}

Could anyone tell the difference(advantages and disadvantages )about those two methods

Thanks in advance !

Why are you using the function in this scenario? By using function calls you are creating the overhead of function call and temporaray object.

I just want to know the advantages and disadvantages of those two methods by this simple example... actually, in practice, especially in memory management application for a special or embedded system, it is necessary to implement our own function to malloc a block of memory. Then the case raises.

I prefer the second form because:

  1. The interface is simpler: one parameter in, the answer returned. You just check whether the pointer is null to verify success. The first form has some kind of other return value to check, which could be boolean, but I cannot tell, so I would have to look up the definitions of OK and NOK. And it is unclear from the interface whether I also need to check the pointer value, or indeed whether the pointer is NULL on failure. Looking into you implementation I can see that OK is returned if and only if the pointer is valid and the pointer is NULL on failure, but then I can write
    text char *my_pmem; my_malloc(64, &my_pmem); if(my_pmem){ ... }

    so the return value is redundant -- it gives me no extra information.
    However, if you want the function to indicate more than just a simple fail/succeed (e.g. different failure modes) then the first way is the only way to do it.
  2. It mimics the standard malloc(3) function -- or it would do if the parameter was of type size_t rather than int -- and therefore has the benefit of familiarity, and makes it easier to port code written with malloc to use my_malloc.

The actual difference is that the first example copies the address of your pmem pointer to the stack and the second example doesn't. The second example only works because you're using malloc() which allocates memory from the heap, otherwise you could have unexpected behavior because you would be returning a local variable (which is cleared upon function completion).

IMHO the second option would be faster because there's one less parameter to be copied to the stack and there's no desreferencing of the pointer's address to obtain the data. Anyway, you should feel no significant speed difference in any of the alternatives.

I can't see any effective difference aside from the extra complications of effectively returning two values in your first example. I'd tend to avoid that kind of redundancy in case my fumble fingers ever cause one to contradict the other.

Like everyone else I too prefer the second method one over the first as it is simpler, easier to understand and uses much less storage in the stack segment. Also I don't see the need for a function call just to malloc a chunk of memory. For an embedded system where resources are scarce you are better off mallocing that block of memory in main.

I think it's just an example. An embedded system often has no OS at all, very few libraries, and do-it-yourself memory management.

Thanks to you all for your comments!
So it is believed that:
(1) there is no actual functional difference between the two methods;
(2) it is needed to pass a pointer-to-pointer to a function only if the original value of the "pointer-to-pointer" parameter is used in the function, or we want to change its value in this function. Otherwise, it only increases the function invoking overhead.
(3) it should be careful when return a local pointer value in a function, because a pointer pointing to stack space(local variables) returned to the invoker points to an invalid space. The pointer returned from a subroutine should point to heap space(like malloc()) or global&static variables.

Is that right ?

Not as you've written them, no.

I think that's correct, though pointers always make for awkward language.

Quite right, stack variables are only valid until the function returns. You can give stack pointers to functions you're calling however, just like you did inside the main() of your first example, since that function is guaranteed to return before main() does.

That was true a couple of decades ago. Nowadays most embedded systems mobile phones for ex. have an OS, virtual memory mgmt and all the libraries. Although the op may be using one that is bare bones but I doubt that otherwise he would not be using malloc and would most likely be coding in assembly language instead of in C.

Small microprocessors are more popular than ever, just not for powering all-singing all-dancing java smartphones. They're in things like MP3 players, wireless mice, cordless phones, monitors, thousands of different USB devices, microwaves, cars... you get the idea. And yes, they are very barebones, and yes, C is very popular for programming them for the most part. There's been a huge explosion of different architectures, developers are fortunate to not have to learn the assembler for them all.