简体   繁体   中英

void pointer to a struct pointer

I have a problem with assigning a void pointer to another struct pointer. My input parameter is changed inside the function semaphoreCreateBinary, but when it returns to main it is empty again. i must probably do some kind of casting but i cannot seem to get it to work.

I will include the code i think is necessary to understand my problem:

From my header file.

typedef struct semaphoreStruct
{
    int               smValue;  
    tcbExtS           *smHolder;  
    int               smCeiling;  
}semaS;

typedef void * SemaphoreHandle;

In my C file

unsigned int semaphoreCreateBinary(void *ro_Handle,unsigned int i_InitialValue)
{
    semaS *Semaphorehandle1;

    Semaphorehandle = malloc (sizeof(*Semaphorehandle));

    Semaphorehandle1->smValue = i_InitialValue;
    ro_Handle = Semaphorehandle1; //seems to get the correct value

    return resultUnInt;
}

int main(void)
{
    SemaphoreHandle s1vPtr;

    semaphoreCreateBinary(&s1vPtr,0);

    int IV = s1vPtr->smValue//s1vPtr is empty again here
}

Any suggestion how to correct this?

EDIT: Even if i pass the argument as an adress with: semaphoreCreateBinary(&s1vPtr,0); It does not work. I cannot change the input type since we got it from our teacher as an API-Spec otherwise i would have changed it.

In C, arguments are passed to functions by value. So, you change only value inside a function. Also, there is another mistake: you don't allocate Semaphorehandle1 . So, there will be segfault. This will be correct:

unsigned int semaphoreCreateBinary(void **ro_Handle,unsigned int i_InitialValue)
{
    semaS *Semaphorehandle1 = malloc(sizeof(semaS));
    Semaphorehandle1->smValue = i_InitialValue;
    *ro_Handle = Semaphorehandle; //seems to get the correct value
    return resultUnInt;
}

Don't forget to free memory after usage.

This works:

unsigned int semaphoreCreateBinary(void *ro_Handle, unsigned int i_InitialValue)
{
    semaS *Semaphorehandle1 = malloc(sizeof(semaS));
    Semaphorehandle1->smValue = i_InitialValue;
    *(semaS**)ro_Handle = Semaphorehandle1;
}

int main(void)
{
    semaS* s1vPtr;
    semaphoreCreateBinary(&s1vPtr, 1);

    int IV = s1vPtr->smValue;

    free(s1vPtr);
    printf("%d\n", IV);
}

Explanation: there are two important insights necessary to understand why this is a useful solution to the question - and as a future software developer you will required to gain those insights yourself:

  1. In C, if you want a function to modify something, you have to pass a pointer to that something. In your case, you want to modify a semaS* pointer (letting it point to the newly malloc ed memory location). So if you want to modify a semaS* , you have to pass a semaS** to the function.
  2. A void* can be cast to any pointer type, including a pointer to a pointer.

Also note that your initial malloc size was wrong. Since you want to allocate a new semaS struct, you have to malloc a memory block of size size(semaS) (you malloc ed a memory block the size of a pointer). Unfortunately, using any other block size will throw no compiler warnings or errors in C. But it will either waste memory (if the block size is too big) or lead to memory corruption (if the block size is too small).

In your code, inside the semaphoreCreateBinary() function

 ro_Handle = Semaphorehandle1;

will not serve your purpose. The pointer ro_Handle itself is passed to the function through pass-by-value, so you cannot change the pointer itself from the function and expect it to reflect that change outside the function. You can change the value pointed by the pointer, it will sustain, but not the pointer.

In case you want to change the pointer, you need to pass the address of the pointer, as a pointer-to-pointer.

Having said that,

semaS *Semaphorehandle1;
Semaphorehandle1->smValue = i_InitialValue;

is pure wrong, as at this point, Semaphorehandle1 is not initialized (ie, not pointing to any valid memory location) and attempt to dereference an uninitialized pointer will lead to undefined behavior , causing segmentation fault. You need to allocate proper memory before you can actually go ahead and dereference that pointer.

In your code ro_Handle = Semaphorehandle1; will not change the value of the pointer in the main scope, as the pointer is a copy (passed by value) in the semaphoreCreateBinary scope. In order to edit the value of a pointer, you need a pointer to it:

unsigned int semaphoreCreateBinary(void **ro_Handle,unsigned int i_InitialValue) {
    ...
    *ro_Handle = Semaphorehandle1;

You then need to pass the address of your pointer to the function:

semaphoreCreateBinary(&s1vPtr,0);

It seems you have some serious misunderstanding about how pointers work. A pointer is a variable that may store the location of a valid variable, but does not have to - this depends on whether you correctly initialize your pointer. Your line

semaS *Semaphorehandle1;

declares an uninitialized pointer, ie a pointer that points to an arbitrary memory location. The next line

Semaphorehandle1->smValue = i_InitialValue;

then dereferences your uninitialized pointer and thus writes to an arbitrary memory locations - this is a typical memory corruption that may lead to undefined behavior for your whole program.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM