AUTOSAR C++14 Rule A27-0-4

Строки в стиле C не должны использоваться

Описание

Определение правила

Строки в стиле C не должны использоваться.

Объяснение

Базовый символьный массив, который хранит строку в стиле C, имеет много недостатков, таких как:

  • Вы должны явным образом обработать выделение и удаление памяти, если вы выполняете операции со строкой, которые требуют нетривиальных манипуляций с памятью.

  • Не всегда понятно, char* ли указывает на один символ или на строку в стиле С.

  • Вы можете случайно преобразовать массив в необработанный указатель, когда передаете его по значению или по указателю на функцию, что приводит к потере информации о размере массива (распад массива). Например, в этом фрагменте кода, func печатает размер указателя на первый символ cString (8), в то время как фактический размер cString равен 6.

    void func(char *c){ //function takes array by value
      cout << sizeof(c);
    }
    
    void main(){
      char cString[]{ "pizza" }; //Size is 6 (5 characters + null terminator)
      func(cString); // Size is 8 (size of char*)
    }

Вместо этого используйте std::string класс для хранения последовательности символов. Класс обрабатывает выделения и деаллокации и создает экземпляр объекта, который можно безопасно передать функциям. Класс также имеет встроенные функциональности для манипулирования строкой, такой как итераторы.

Реализация Polyspace

Polyspace® флаги использования:

  • Указатели на char (char*) и массивы char (char someArray[]).

  • Указатели на и массивы char с определителем типа, таким как volatile или const. Для примера char const*.

  • Указатели на и массивы типов wchar_t, char16_t, и char32_t.

Если у вас есть объявление функции и его определение в исходном коде, Polyspace помещает нарушение в определение функции. Для примера:

const char* greeter(void);
//....
const char* greeter(void){ //Non-compliant
  return "Hello"; 
}

Polyspace не помечает использование:

  • Указатели на или массивы signed или unsigned char. Для примера, signed_c и unsigned_arr не помечены в этом фрагменте кода:

    signed char* signed_c;
    unsigned char unsigned_arr[2048];

  • Буквальные строки. Для примера возврата значение greeter() отмечен не в этом фрагменте кода, а использованием const char* в первой линии помечено:

    const char* greeter(void){ //Non-compliant
      return "Hello"; // Compliant
    }

  • Параметры main().

Поиск и устранение проблем

Если вы ожидаете нарушения правил, но не видите его, обратитесь к разделу «Стандартные нарушения кодирования не отображаются».

Примеры

расширить все

#include<iostream>
#include <string>
#include<cstring>

char* sub_c_str(   //Non-compliant
    const char* str1, const int delim)  //Non-compliant
{
    size_t index {strlen(str1)};
    if (strchr(str1, delim)) {
        index = (size_t)(strchr(str1, delim) - str1);
    }
    char* p = (char*) malloc(index + 1); //Non-compliant
    //memory leak if p is not freed by caller
    strncpy(p, str1, index);
    return p;

}

std::string sub_str(std::string const str2, const char delim)
{
    return str2.substr(0, str2.find(delim));
}

int main()
{
    const char str1[] { "rootFolder/subFolder"}; // Non-compliant
    std::cout << sub_c_str(str1, '/') << std::endl;

    std::string const str2 { "rootFolder/subFolder" };
    std::cout << sub_str(str2, '/') << std::endl;
    return 0;
}

В этом примере функция sub_c_str возвращает подстроку строкового параметра C-стиля str1 до, но не включая первый образец delim. Тип возврата и первый параметр sub_c_str оба являются несовместимыми указателями на char. Указатель на p, который хранит подстроку, также не соответствует. Обратите внимание, что если вы не освобождаете память, выделенную p до окончания программы это приводит к утечке памяти.

Функциональные sub_str использует преимущества std::string класс для выполнения той же операции, что и sub_c_str. Класс обрабатывает выделение и отмену выделения памяти. Класс также имеет встроенные функциональности (find и subst) для выполнения манипуляции строками.

Проверяйте информацию

Группа: Библиотека ввода/вывода
Категория: Необходимый, Автоматизированный
Введенный в R2021a