这有什么错铸像(无效**)及device_array? [英] What's wrong with casting like (void**)&device_array?
问题描述
有关于使用 cudaMalloc((无效的另外一个问题这个答案
** )及device_array,NUM_BYTES),它使用无效**
作为输出参数,而不是通过一个无效*
像标准的返回值的malloc
。
There is this answer on another question about the use of cudaMalloc((void**)&device_array, num_bytes)
, which uses void**
as output argument instead of passing a void*
as return value like the standard malloc
.
它批评NVIDIA的API,并指出:
It criticizes NVIDIA's API and states :
铸造,如(无效**)及device_array,是无效的C和结果
未定义的行为。
Casting, as in (void**)&device_array, is invalid C and results in undefined behavior.
,并已upvoted几次(8截至目前),所以我认为有一定的道理在里面。
and has been upvoted several times (8 as of now), so I assume there is some truth in it.
我不明白这有什么错铸那里。
I don't understand what's wrong with casting there.
- 什么是无效这儿用?
- 在什么情况下会这导致不确定的行为?
我所知道的是,它编译没有警告,与我预期的行为运行。但我不掌握相关C到标准规范的水平。
All I know is that it compiles without warning and runs with the intended behavior for me. But I am not knowledgeable with C up to standard specification level.
推荐答案
的问题是,无效*
有一个在C特殊的含义,具有特殊的规则(1)。它是唯一指针类型/从中你可以安全地将任何其他指针类型。然而,这些特殊规则不递归适用无效**
。
The problem is that void*
has a special meaning in C, with special rules (1). It is the only pointer type to/from which you can safely convert any other pointer type. However, these special rules do not apply recursively to void**
.
意思就是说code像为int * PTR =的malloc(X);
是完全没有问题的,但
Meaning that code like int* ptr = malloc(x);
is perfectly fine, but
int* ptr;
cudaMalloc(&ptr, x); // bad
不精!从 INT **
A指针转换为无效**
是不明确。理论上,这可能会导致不确定的行为和不对(2)。
is not fine! A pointer conversion from int**
to void**
is not well-defined. In theory this could cause undefined behavior and misalignment (2).
在另外,也可能是与指针锯齿问题。编译器是免费的假设的无效**
从未通过 INT访问**
和内容可以因此,优化以意想不到的方式在code,导致对违反严格别名规则(6.5)的未定义的行为。
In addition, there might also be problems with pointer aliasing. The compiler is free to assume that the contents of a void**
is never accessed through a int**
and could therefore optimize the code in unexpected ways, leading to undefined behavior for violation of the strict aliasing rule (6.5).
这意味着你将不得不写code这样才能安全地使用功能:
Which means you will have to write code like this in order to safely use the function:
void* vptr;
int* iptr;
cudaMalloc(&vptr, x);
iptr = vptr;
(1)C11 6.3.2.3/1:
(1) C11 6.3.2.3/1:
要无效的指针可被转换成或从一个指针到任何物体
类型。的指针的任何对象类型可被转换成一个指针
作废,然后再返回;结果应比较等于原
指针。
A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
(2)C11 6.3.2.3/7:
(2) C11 6.3.2.3/7:
一个指针对象类型可被转换成一个指针
不同的对象类型。如果所得到的指针不正确
为引用类型一致,行为是不确定的。
A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined.
这篇关于这有什么错铸像(无效**)及device_array?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!