我做了这样的功能:
bool IsSameString(char* p1, char* p2)
{
return 0 == strcmp(p1, p2);
}
问题在于,有时错误地传递的参数不是字符串(意味着p1
或p2
不以空字符结尾)。
然后,strcmp
继续比较,直到它到达不可访问的内存并崩溃。
是否有strcmp
的安全版本?或者我能否以安全的方式判断p1
(和p2
)是否为字符串?
答案 0 :(得分:16)
不,没有(标准)方法来判断char *
是否实际指向有效内存。
在您的情况下,最好对所有字符串使用std::string
而不是char *
,以及重载的==
运算符。如果这样做,编译器将强制执行类型安全。
编辑:根据下面的评论,如果您发现自己有时会将char *
传递给可能会或可能不是有效字符串的函数,而这些字符串可能会使用以null结尾的字符串那么你的方法基本上是错误的,所以基本上
@ janm的答案如下。
答案 1 :(得分:13)
在某些情况下,std::strncmp
可以解决您的问题:
int strncmp ( const char * str1, const char * str2, size_t num );
它将C字符串str1的num个字符与C字符串str2的字符数进行比较。
另外,看看美国国土安全部国家网络安全部recommends对此事的看法:
确保在传入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 */ }
答案 2 :(得分:10)
如果您将字符串传递给非空终止的strcmp(),那么您已经丢失了。您有一个非空终止字符串(但应该是)的事实表明您的代码中存在更深层次的问题。你不能改变strcmp()来安全地处理这个问题。
您应该编写代码,以免永远发生。首先使用字符串类。在将数据导入代码的边界处,您需要确保处理特殊情况;如果你得到太多的数据,你需要做正确的事。这不涉及逃避缓冲区的结束。如果必须在C样式缓冲区中执行I / O,请使用指定缓冲区长度的函数,并检测并处理缓冲区在此时不够大的情况。
答案 3 :(得分:6)
便携式无法解决这个问题。约定规定,有一个额外的字符,其中包含一个空字符,该字符属于与字符串本身相同的正确分配的内存块。遵循此约定并且发生一切正常或未定义的行为。
如果您知道与之比较的字符串的长度,则可以使用strncmp()
但如果传递给您的代码的字符串实际上比您比较的字符串短,则无效。
答案 4 :(得分:3)
你可以使用strncmp,但是如果可能的话,使用std :: string来避免很多问题:)
答案 5 :(得分:1)
您可以使用strncmp功能对要比较的字符数设置上限。
答案 6 :(得分:-1)
没有最佳答案,因为您无法验证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 ) {}
答案 7 :(得分:-2)
你不写,你正在使用什么平台。 Windows具有以下功能:
如果您使用的是Windows,那么 IsBadStringPtr
可能就是您要找的。 p>