我做了一个这样的函数:
bool IsSameString(char* p1, char* p2)
{
return 0 == strcmp(p1, p2);
}
问题是,有时错误地传递了不是字符串的参数(这意味着p1
orp2
不以空字符终止)。然后,strcmp
继续比较,直到它到达不可访问的内存并崩溃。有安全的版本strcmp
吗?或者我可以以安全的方式判断p1
(and p2
) 是否是字符串?
不,没有(标准)方法可以判断 a 是否char *
实际指向有效内存。
在您的情况下,最好对所有字符串使用std::string
而不是char *
s 以及重载==
运算符。如果您这样做,编译器将强制执行类型安全。
编辑:根据下面的评论,如果您发现自己有时将char *
可能是或可能不是有效字符串的 s 传递给期望以空结尾的字符串的函数,那么您的方法从根本上是错误的,所以基本上@janm 的回答如下.
在某些情况下std::strncmp
可以解决您的问题:
int strncmp ( const char * str1, const char * str2, size_t num );
它将 C 字符串 str1 的最多 num 个字符与 C 字符串 str2 的字符进行比较。
另外,看看美国国土安全部国家网络安全部门对此事的建议:
确保字符串在传递到 strcmp 之前为空终止。这可以通过始终在缓冲区的最后分配字节中放置一个 \0 来强制执行。
char str1[] ="something";
char str2[] = "another thing";
/* In this case we know strings are null terminated. Pretend we don't. */
str1[sizeof(str1)-1] = '\0';
str2[sizeof(str2)-1] = '\0';
/* Now the following is safe. */
if (strcmp(str1, str2)) { /* do something */ } else { /* do something else */ }
如果您将字符串传递给 strcmp() 不是空终止的,那么您已经丢失了。您的字符串不是以空结尾(但应该是)的事实表明您的代码中存在更深层次的问题。您无法更改 strcmp() 以安全地处理此问题。
您应该编写代码,这样就永远不会发生。从使用字符串类开始。在将数据放入代码的边界处,您需要确保处理异常情况;如果您获得太多数据,您需要做正确的事。这不涉及耗尽缓冲区的末端。如果您必须对 C 风格的缓冲区执行 I/O,请使用指定缓冲区长度的函数,并检测和处理缓冲区在该点不够大的情况。
便携式无法治愈。约定规定有一个额外的字符包含一个空字符,该字符属于与字符串本身相同的正确分配的内存块。要么遵循此约定,要么发生一切正常或未定义的行为。
如果您知道要比较的字符串的长度,则可以使用strncmp()
,但如果传递给您的代码的字符串实际上比您比较的字符串短,他将无济于事。
你可以使用strncmp,但如果可能的话使用std::string来避免很多问题:)
您可以使用strncmp函数对要比较的字符数设置上限。
对此没有最佳答案,因为您无法验证 char* 是字符串。唯一的解决方案是创建一个类型并将其用于字符串,例如 str::string 或者如果您想要更轻的东西,请创建您自己的类型。IE
struct MyString
{
MyString() : str(0), len(0) {}
MyString( char* x ) { len = strlen(x); str = strdup(x); }
⁓MyString() { if(str) free(str); }
char* str;
size_t len;
};
bool IsSameString(MyString& p1, MyString& p2)
{
return 0 == strcmp(p1.str, p2.str);
}
MyString str1("test");
MyString str2("test");
if( IsSameString( str1, str2 ) {}
你不写,你用的是什么平台。Windows 具有以下功能:
IsBadStringPtr
如果您使用的是 Windows,可能是您正在寻找的东西。