Main Content

Result of string::c_str() compared to another pointer

The C string obtained from std::string::c_str() is compared to a pointer (or NULL)

Since R2021b

Description

This defect occurs when a C string that is obtained by calling the std::string::c_str function is compared to a pointer or a NULL. For instance, Polyspace® flags the comparison operations in the if statements in this code:

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
	//..
	}
	//..
}

Risk

Comparing a pointer to the C string obtained from a string has these risks:

  • When you compare the output of std::string::c_str to a pointer, the addresses of the pointers are compared. You might expect the compiler to compare the content of the pointers. For instance, in the preceding code, you might expect that (p==pStr) evaluates to true because both pointers contains loren ipsum. The compiler compares the addresses p and pStr, which evaluates to false. Comparing pointers as a method of comparing strings produces unexpected results.

  • The C string p that is obtained by calling std::string::c_str() is always non-NULL. The expression (p==NULL) always evaluates to false. Comparing such a C string to NULL might produce unexpected results and indicates a logic error in the code.

Fix

To fix this issue:

  • To compare the content of strings, use string functions or use operators with the string objects directly.

  • Because std::string::c_str() always returns a non-NULL value, remove the comparison to NULL or refactor your logic.

Examples

expand all

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

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

In this example, the function setName sets the category name when the C string obtained from the string s is non-NULL. You might expect the condition (s.c_str() != NULL) to evaluate to true only when s contains a string of nonzero length. Because std::string::c_str() returns a non-NULL value regardless of the content of the string object, the condition always evaluates to true. As a result, this comparison is unnecessary and cannot detect empty strings.

Correction — Use string::empty to Detect Empty

To fix this defect, remove the comparison of the C string to NULL. To detect empty string, use 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              
}

In this example, C strings pStr1 and pStr2 are obtained by calling string::c_str() and then compared to other pointers. In is_same, you might expect (pStr1 == pStr2) to evaluate to true if the contents of s1 and s2 contains the same string. Because this operation is a pointer comparison, it compares the address of the pointers pStr1 and pStr2 instead of the content of the string, producing unexpected results.

When comparing string objects and C strings, you might expects comparison operations such as (pStr1 != Cstr) to compare the content of the string and char pointer. Because this operation compares the addresses of the pointers instead of the string contents, the results might be unexpected.

Correction — Use Member Functions and Overloaded Operators of std::string

To fix this defect, use the member functions and overloaded operators of std::string to compare strings and C strings.

#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);              
}

Result Information

Group: Programming
Language: C++
Default: Off
Command-Line Syntax: STD_STRING_C_STR_COMPARED_TO_POINTER
Impact: Low

Version History

Introduced in R2021b