有没有安全的strcmp?

时间:2009-10-26 09:02:22

标签: c++ c strcmp

我做了这样的功能:

bool IsSameString(char* p1, char* p2) 
{
     return 0 == strcmp(p1, p2);
}

问题在于,有时错误地传递的参数不是字符串(意味着p1p2不以空字符结尾)。 然后,strcmp继续比较,直到它到达不可访问的内存并崩溃。 是否有strcmp的安全版本?或者我能否以安全的方式判断p1(和p2)是否为字符串?

8 个答案:

答案 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可能就是您要找的。