有没有安全的strcmp?

P-P*_*P-P 12 c c++ strcmp

我做了这样的功能:

bool IsSameString(char* p1, char* p2) 
{
     return 0 == strcmp(p1, p2);
}
Run Code Online (Sandbox Code Playgroud)

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

Wer*_*sey 17

不,没有(标准)方法来判断char *实际是否指向有效内存.

在您的情况下,最好使用std::string而不是char *s来表示所有字符串,以及重载==运算符.如果这样做,编译器将强制类型安全.

编辑:根据下面的评论,如果你发现自己处于这样的情况,你有时将char *s可能或不是有效的字符串传递给期望以null结尾的字符串的函数,那么你的方法基本上是错误的,所以基本上@janm的答案如下.

  • ..如果你使用std :: string,你不需要写一个像你写的那样的函数,节省你的时间和精力. (3认同)
  • 如果其中一个字符串是从某个地方作为输入提供的,那么使用std :: string仍然无济于事.在一天结束时,必须从char*实例化std :: string.如果该char*未指向以null结尾的字符串,则std :: string构造函数将会爆炸或具有未定义的行为.唯一的*true*解决方案是以某种方式对字符串进行最大长度的清理(在构建std :: string实例时,如果我们继续该路由,或者在使用strncmp而不是strcmp时,则执行以null结尾的char*路由). (3认同)

Igo*_*Oks 14

在某些情况下std::strncmp可以解决您的问题:

int strncmp ( const char * str1, const char * str2, size_t num ); 
Run Code Online (Sandbox Code Playgroud)

它将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 */ }
Run Code Online (Sandbox Code Playgroud)


jan*_*anm 10

如果您将字符串传递给非空终止的strcmp(),那么您已经丢失了.您有一个非空终止字符串(但应该是)的事实表明您的代码中存在更深层次的问题.你不能改变strcmp()来安全地处理这个问题.

您应该编写代码,以便永远不会发生.首先使用字符串类.在将数据导入代码的边界处,您需要确保处理特殊情况; 如果你得到太多的数据,你需要做正确的事.这不涉及逃避缓冲区的结束.如果必须将I/O执行到C样式缓冲区,请使用指定缓冲区长度的函数,并检测并处理缓冲区在该点处不够大的情况.

  • 是的,詹姆说.当您发现错误时,请修复该错误.不要只是试图隐藏它,使其他代码复杂化,以使bug的症状不那么严重.在这种情况下,代码中存在一个调用IsSameString()的错误. (3认同)

sha*_*oth 6

便携式无法解决这个问题.约定规定,有一个额外的字符,其中包含一个空字符,该字符属于与字符串本身相同的正确分配的内存块.遵循此约定并且发生一切正常或未定义的行为.

如果你知道你比较的字符串的长度你可以使用,strncmp()但如果传递给你的代码的字符串实际上比你比较的字符串短,他将无济于事.