题
我做了一个这样的函数:
bool IsSameString(char* p1, char* p2)
{
return 0 == strcmp(p1, p2);
}
问题是,有时,错误地传递的参数不是字符串(这意味着 p1
或者 p2
不以空字符终止)。然后, strcmp
继续比较,直到到达不可访问的内存并崩溃。有安全版本吗 strcmp
?或者我可以告诉是否 p1
(和 p2
) 是字符串还是不安全?
解决方案
不,没有(标准)方法来判断 char *
是否实际指向有效内存。
在您的情况下,最好对所有字符串使用 std :: string
而不是 char *
,以及重载的 ==
运算符。如果这样做,编译器将强制执行类型安全。
编辑:根据以下评论,如果您发现自己处于有时会传递 char *
的情况,这些字符可能是也可能不是有效的字符串以null结尾的字符串然后基本上是你的方法的根本错误
@ 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,或者如果你想要更轻的话,可以创建自己的类型。即
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,可能就是您正在寻找的。