2
votes

What is the difference between (void **)&x and (void *)x? I will give you some code, please help me out.

float *xd;
int size=width*width*size(float);
cudaMalloc((void **)&x,size); 1
cudaMalloc((void *)x,size);   2
cudaMalloc(&x,size);          3
cudaMalloc(*x,size);          4

cudaFree(xd);

I just want to know the difference.

The first parameter of the cudaMalloc() function is the address of a pointer variable that must point to the allocated object after allocation. The address of the pointer variable should be cast to (void **) because the function expects a generic pointer value; the memory allocation function is a generic function that is not restricted to any particular type of objects. This address allows the cudaMalloc() function to write the address of the allocated object into the pointer variable.3 The second parameter of the cudaMalloc() function gives the size of the object to be allocated, in terms of bytes. The usage of this second parameter is consistent with the size parameter of the C malloc() function.

2
C++decl may be of use hereEric
It's much the same as the difference between &x and x. Questions like this aren't useful without knowing why you might think that two very different things are the same.Jim Balter

2 Answers

6
votes

They're just about completely different.

This:

(void **)&x

takes the address of x and converts it to void** (pointer to pointer to void).

This:

(void *)x

takes the value of x and converts it to void*.

They're both pointers, but they point to entirely different locations in memory (unless x happens to contain its own address), and they're of different types.

And if you want to show us code, it would be helpful to show us code that actually compiles. Copy-and-paste your actual source code; don't re-type it. You haven't shown us the declaration of x (is xd a typo for x?), and size(float) is a syntax error (did you mean sizeof(float)?).

2
votes

To give you a better understanding why with cudaMalloc you often write (void**)&var, consider the following:

cudaMalloc allocates a memory on the GPU. The memory type it is referred is void* as it does not really care about the data type.

Once we have the address of that memory inside the cudaMalloc we just allocated, we need to somehow return it to the caller. But all CUDA API functions are returning error codes (or success code) and any additional returned data has to be passed back by parameter reference.

C language has no pass-by-reference, so you actually need to pass a pointer to a variable where you want the function to store the result. Since you want to store a pointer value, you need to pass a pointer-to-pointer. Hence void** type.

If one wanted to encapsulate a malloc in similar way, one would write something like this:

void myMalloc(void** ret, size_t size) {
    void* mem = malloc(size);
    *ret = mem;
}

Now, if you pass (void**)&var to myMalloc, the function will be able to overwrite the value of the var --- as ret will be pointing to var variable.

Does this make it clearer?