Преобразование указателя на X в массив X - PullRequest
0 голосов
/ 03 июня 2019

"Не надо!"это правильный ответ, но, к сожалению, это не тот, который мне нужен.

Если я сделаю:

size_t array_size = func_that_calc_array_size();
char *foo = new char[array_size];
if (array_size > 42)
    foo[42] = 'X';

Это все совершенно правильно, но моя программа проверки кода MISRA C ++ выдает ошибку 5-0-15 на foo[42], который говорит, что «индексирование массива должно быть единственной формой арифметики указателей».Этот вопрос фактически задавался до , но в этом вопросе и ответе пропущена критическая проблема, а именно то, что в документации далее говорится:

Индексирование массива должно применяться только к объектам, определенным кактип массива.

Если вы посмотрите на документацию (подозрительную загрузочную копию можно найти, выполнив поиск по запросу "misra c ++ 2008 pdf"), у нее есть пример, подобный следующему:

void my_fn(uint8_t *p1, uint8_t p2[])
{
    p1[5] = 0; // Non-compliant - p1 was not declared as array
    p2[5] = 0; // Compliant
}

Итак, в основном инструмент проверки кода сопоставляет объявление с использованием.Есть ли какой-нибудь возможный способ преобразовать указатель в массив?


В нашем реальном примере мы используем OpenCV uchar *cv::Mat::ptr(), поэтому мы не можем просто зарезервировать достаточно большой массив.

Ответы [ 2 ]

1 голос
/ 03 июня 2019

Я думаю, корень проблемы здесь char *foo = new char[array_size];.Возможно, контролеру MISRA позволено предположить, что это не массив, поскольку все динамическое распределение памяти запрещено.

Вы можете попытаться увидеть, получаете ли вы ту же ошибку при написании char array[10]={0}; char* foo = array;, потому что тогда вы можете отклонить это как ложную ошибку инструмента.

Цель и обоснование правила состоит в том, чтобызабанить форму *(x + i) вместо x[i].Ничего больше.Правило не блокирует использование [] для операнда указателя.

Однако существует несколько правил MISRA, обеспечивающих выполнение всей арифметики указателей с операндами, указывающими на один и тот же массив, для предотвращения неопределенного поведения.

MISRA-C: 2004 и MISRA-C ++В 2008 году также было какое-то странное, смутное требование, чтобы параметры функции были объявлены как char param[], а не char* param, но, поскольку это было бессмысленным, весь этот разговор об индексации стиля массива был удален в MISRA-C: 2012.

(На самом деле в C или C ++ нет такой вещи, как «индексация стиля массива», см. Поддерживают ли указатели «индексацию стиля массива»? )

1 голос
/ 03 июня 2019

Действительность правила довольно сомнительна.В этом примере p1 и p2 имеют абсолютно одинаковый тип: они оба указатели.

Если p2 действительно соответствует правилу, то решение состоит в том, чтобы ввести функцию, чтобы выможет использовать функцию-аргумент-массив-указатель-корректировка.Вот пример с лямбда-выражением, но вы также можете использовать обычную функцию:

char *foo = new foo[array_size];
if (array_size > 42)
    [](char foo[]) {
        foo[42] = 'X';
    }(foo);

C ++ 20 вводит std::span, что, по-видимому, является решением проблемы:

std::span foo_span{foo, array_size};
if (array_size > 42)
    foo_span[42] = 'X';

При этом используется перегрузка класса оператора индекса, а не указатель-индекс, поэтому он соответствует правилу.std::span, вероятно, не реализуемо без нарушения MISRA, но в стандартной библиотеке есть много других вещей, поэтому я подозреваю, что это не проблема.


В нашем реальном примере мыиспользуя OpenCV uchar *cv::Mat::ptr(), поэтому мы не можем просто зарезервировать достаточно большой массив.

Возможно, чтобы следовать духу правила, а не буквы, вы должны передать cv::Mat&в функцию, а не char*.

PS Я подозреваю, что OpenCV не соответствует MISRA, поэтому, в зависимости от этого, вероятно, это не лучшая вещь, если программа должна соответствовать MISRA.

...