C string from string::c_str() compared to pointer

Струна до получена из std::string::c_str() сравнивается с указателем (или NULL)

Описание

Этот дефект происходит, когда струна до, которая получена путем вызова std::string::c_str функция сравнивается с указателем или NULL. Например, Polyspace® отмечает операции сравнения в if операторы в этом коде:

void foo(){
	//...
	std::string str{"loren ipsum"};
	//...
	const char pStr[] = "loren ipsum";
	const char* p = str.c_str();
	if(p==NULL){//Defect: Unnecessary
		
	}
	if(p==pStr){ //Defect: Compares pointer address
	//..
	}
	//..
}

Риск

Сравнение указателя на струну до получено из string имеет эти риски:

  • Когда вы сравниваете выход std::string::c_str к указателю сравнены адреса указателей. Вы можете ожидать, что компилятор сравнит содержимое указателей. Например, в предыдущем коде, вы можете ожидать тот (p==pStr) оценивает к true потому что оба указателя содержат loren ipsum. Компилятор сравнивает адреса p и pStr, который оценивает к false. Сравнение указателей как метод сравнения строк приводит к неожиданным результатам.

  • Струна до p это получено путем вызова std::string::c_str() является всегда непустым. Выражение (p==NULL) всегда оценивает к false. Сравнение такой струны до к NULL может привести к неожиданным результатам и указывает на логическую ошибку в коде.

Исправление

Устранить эту проблему:

  • Чтобы сравнить содержимое строк, используйте строковые функции или используйте операторы с объектами строки непосредственно.

  • Поскольку std::string::c_str() всегда возвращает ненулевое значение, удалите сравнение с NULL или осуществите рефакторинг свою логику.

Примеры

развернуть все

#include<string>
extern void setCategoryName(const char *);

void setName(const std::string &s)
{
    if (s.c_str() != NULL)//Defect                     
    {
        setCategoryName(s.c_str());                
    }
}

В этом примере, функциональном setName устанавливает название категории, когда струна до получила из строки s non-NULL. Вы можете ожидать условие (s.c_str() != NULL) оценивать к true только, когда s содержит строку ненулевой длины. Поскольку std::string::c_str() возвращает non-NULL значение независимо от содержимого объекта строки, условие всегда оценивает к true. В результате это сравнение является ненужным и не может обнаружить пустые строки.

Коррекция — использует string::empty обнаружить пустой

Чтобы зафиксировать этот дефект, удалите сравнение струны до к NULL. Чтобы обнаружить пустую строку, используйте std::string::empty().

#include<string>

extern void setCategoryName(const char *);
void setName_possibleFix1(const std::string &s)
{
	setCategoryName(s.c_str());                    
}

void setName_possibleFix2(const std::string &s)
{
	if (!s.empty())                                 
	{
		setCategoryName(s.c_str());                 
	}
}
#include<string>
bool is_same(const std::string &s1, const std::string &s2)
{
	const char* pStr1 = s1.c_str();
	const char* pStr2 = s2.c_str();
	return (pStr1 == pStr2);//Defect             
}
bool is_different(const std::string &s1, const char* Cstr)
{
	const char* pStr1 = s1.c_str();
	return (pStr1 != Cstr);//Defect              
}

В этом примере, струны до pStr1 и pStr2 получены путем вызова string::c_str() и затем по сравнению с другими указателями. В is_same, вы можете ожидать (pStr1 == pStr2) оценивать к true если содержимое s1 и s2 содержит ту же строку. Поскольку эта операция является сравнением указателя, она сравнивает адрес указателей pStr1 и pStr2 вместо содержимого строки, приводя к неожиданным результатам.

При сравнении объектов строки и струн до, вы можете ожидать операции сравнения, такие как (pStr1 != Cstr) сравнить содержимое строки и char указатель. Поскольку эта операция сравнивает адреса указателей вместо содержимого строки, результаты могут быть неожиданными.

Коррекция — использует функции членства и перегруженные операторы std::string

Чтобы зафиксировать этот дефект, используйте функции членства и перегруженные операторы std::string сравнить строки и струны до.

#include <string>

bool is_same(const std::string &s1, const std::string &s2)
{
    return (s1 == s2);             
}
bool is_different(const std::string &s1, const char* Cstr)
{
	return (s1!= Cstr);              
}

Информация о результате

Группа: Программирование
Язык: C++
Значение по умолчанию: Off
Синтаксис командной строки: STD_STRING_C_STR_COMPARED_TO_POINTER
Удар: низко
Введенный в R2021b