Подтвердить что ты не робот

Что не так с литьем (void **) и device_array?

Существует этот ответ по другому вопросу об использовании cudaMalloc((void**)&device_array, num_bytes), который использует void** как выходной аргумент вместо передачи void* в качестве возвращаемого значения как стандартный malloc.

Он критикует API NVIDIA и заявляет:

Кастинг, как и в (void **) и device_array, недействителен C и приводит к undefined.

и был увеличен несколько раз (8 на данный момент), поэтому я предполагаю, что в нем есть какая-то правда.

Я не понимаю, что случилось с кастингом.

  • Что здесь недействительно?
  • В каком случае это приведет к поведению undefined?

Все, что я знаю, это то, что он компилируется без предупреждения и работает с предполагаемым поведением для меня. Но я не осведомлен с C до стандартного уровня спецификации.

4b9b3361

Ответ 1

Проблема заключается в том, что void* имеет особое значение в C, со специальными правилами (1). Это единственный тип указателя, из которого вы можете безопасно конвертировать любой другой тип указателя. Однако эти специальные правила не применяются рекурсивно к void**.

Значение этого кода, как int* ptr = malloc(x);, отлично, но

int* ptr; 
cudaMalloc(&ptr, x); // bad

не в порядке! Преобразование указателя из int** в void** не определено. Теоретически это может привести к поведению и несоосности w90 > (2).

Кроме того, могут возникнуть проблемы с наложением указателя. Компилятор может предположить, что содержимое void** никогда не получает доступа через int** и поэтому может оптимизировать код неожиданными способами, приводя к поведению undefined за нарушение правила строгого сглаживания (6.5).

Это означает, что вам нужно будет написать такой код, чтобы безопасно использовать эту функцию:

void* vptr; 
int*  iptr;

cudaMalloc(&vptr, x);
iptr = vptr;

(1) C11 6.3.2.3/1:

Указатель на void может быть преобразован в или из указателя на любой объект тип. Указатель на любой тип объекта может быть преобразован в указатель на пустота и обратно; результат сравнивается с оригиналом указатель.

(2) C11 6.3.2.3/7:

Указатель на тип объекта может быть преобразован в указатель на другой тип объекта. Если результирующий указатель неверен выровненный для ссылочного типа, поведение undefined.