Malloc to void pointer fails

I have a function to which I will pass a struct ID and it will return me a string.
I will pass a pointer to store the name string and that pointer will be allocated memory by the function called.

int ConvertIDToName(void *id, void *name, size_t *size)
{
    int         status = 0;
    unsigned char *xIDname = "user4.microsoft.com";

    *name = (unsigned char*)malloc(30);
    memcpy(*name, xIDName, *size);

    ...

    return(0);
}
main(int argc, char* argv[])
{
    struct ID_t idObj ={1,5, {0,0,0,0,0,5}};
    unsigned char*        IDName = NULL;
    UINT32            IDNameSize = MAX_CHAR;

    ConvertIDToName(&idObj, &IDName, (size_t *)&IDNameSize);

    return(0);
}

The function ConvertIDToName() fails to store the allocated memory address in the void pointer.
I am unable to assign memory in the pointer and it gives me error from 3rd statement of function ConvertIDToName():

 
   warning: dereferencing �void *� pointer
    test_code.c:683: error: invalid use of void expression

What am I doing wrong?

---------- Post updated at 02:33 AM ---------- Previous update was at 02:32 AM ----------

I missed the simple thing of typecasting the void pointer before using it.
This solves the issue:

*(unsigned char **)name = malloc(30);
memcpy(*(unsigned char **)name, xIDName, *size);

Why is it 'void' in the first place? Make it a char **, and no typecasting is necessary.

1 Like

Your code crashes because you are passing the address that "name" is pointing to
which is null.

So what you must do is pass the address of name as

int ConvertIDToName(void *id, void *&name, size_t *size) {     int         status = 0;     unsigned char *xIDname = "user4.microsoft.com";      *name = (unsigned char*)malloc(30);  /* this will work with the change */     memcpy(*name, xIDName, *size);      ...      return(0); }

---------- Post updated at 08:08 AM ---------- Previous update was at 08:05 AM ----------

int ConvertIDToName(void *id, void *&name, size_t *size) { int status = 0; unsigned char *xIDname = "user4.microsoft.com"; name = (unsigned char)malloc(30); memcpy(*name, xIDName, *size); ... return(0); }

1 Like

why does the ConvertIDToName prototype say "void * id" instead of "struct ID_t *" madness!!!

That's probably where your warning is. Don't use void * explicitly generally.

Is it really worth malloc'ing 30 bytes?
just declare a char array[30]

I don't see why 30 bytes? I mean you have GB of RAM are you saving it all for Christmas?
Will 30 bytes always be enough? 1024 may be enough if times change.

Give yourself some room for possible growth. And use powers of two, 64. 128, 256, 1024 etc.

:slight_smile:

There is a lot of opinion in this thread, which is okay as long as a reader knows that fact.

Generally it is bad idea to cast malloc, because it is not required and may introduce subtle bugs that are hard to find, a discussion:

FAQ > Casting malloc - Cprogramming.com

Consider the use of a debugger, ex: gdb. This will help resolve crashes by examining core files, link:

RMS's gdb Tutorial: Segmentation Fault Example

Finally, allocating heap memory (malloc does this for you in C) is not all that simple.
If you allocate x+1 bytes for a string which should never be long than x, you have to check input carefully, otherwise if the string you enter is too long by a few bytes it probably will not segfault, it will simply trash a neighboring variable. Nasty.

Except for embedded systems (ex ARM), declaring strings longer than needed is less harmful, but still requires checking EVERY input string before parking it in the variable, because this makes an entry for a possible code exploit. Shell code and SQL injection come to mind.

malloc works this way in general:

  1. at the beginning of code invocation, the brk() system call allocates pages of memory, and those pages then are controlled by malloc, not directly by your program code, normally. Do not call brk() on your own if you use malloc or functions like strdup which call malloc. Calling brk() directly in code that uses malloc usually results in chaos.

So if you malloc 10 bytes and page size is 8192 bytes (example), then you still have more already allocated memory available.

  1. malloc keeps track of what it allocates, pages are in a page table, variables are tracked usually with some kind of descriptor. The descriptor is often a struct that consists of a pointer to the start of the variable (what malloc returns to you), and a length in bytes.

hypothetical example base on Doug Lea's original malloc:

[address of word aligned memory][length].... [word aligned memory]

So, if you increment or decrement the pointer you have (your variable) it no longer references [address of word aligned memory]. This causes free() to get nasty with you.

  • finally, some of the suggestions in this thread are just that - there is both art and science in building good code.

This is also potentially nasty:

(size_t *)&IDNameSize

How do you know that IDNameSize is a size_t? It's not defined as a size_t, it's defined as a UINT32.

UINT32 is not a size_t. Only size_t is size_t, which is why declarations use it in the first place. There are other address models than ILP32. Just try compiling on 64-bit Linux and you'll wind up with an LP64 binary.