【问题标题】:Am I correct that strcmp is equivalent (and safe) for literals?我是否正确认为 strcmp 对于文字是等效的(并且安全的)?
【发布时间】:2010-10-01 16:54:39
【问题描述】:

我们都知道溢出可能导致的问题,这就是 strn* 存在的原因——而且大多数时候它们是有意义的。但是,我已经看到使用 strncmp 来比较命令行参数的代码,如下所示:

if(... strncmp(argv[i], "--help", 6) == 0

现在,我认为这是不必要的,甚至可能是危险的(对于较长的参数,很容易误算文字中的字符)。

strncmp 在空值上停止,并且代码已经假定 argv[i] 是空终止的。任何字符串文字都保证以空值结尾,那么为什么不使用 strcmp 呢?

也许我遗漏了一些东西,但我已经看过几次了,这一次引起了我的兴趣。

【问题讨论】:

    标签: c strcmp


    【解决方案1】:

    您确定该代码不打算匹配 "--helpmedosoemthingwithareallylongoptionname"?

    【讨论】:

    • 这似乎是一种明显的可能性。
    • 这是一个很好的观点。我不认为在这种情况下,因为所有命令行参数都是以这种方式完成的
    • 更可能的意图是匹配 --help=foobar 之类的东西,但不幸的是它也会匹配 --helper-program 之类的东西。我认为代码有问题。
    【解决方案2】:

    呃...从技术上讲,这样的事情不可能发生吗?

    char *cp1 = "help";
    cp1[4] = '!'; // BAD PRACTICE! don't try to mutate a string constant!
    // Especially if you remove the terminating null!
      ...
    strcmp(some_variable, "help"); 
    // if compiler is "smart" enough to use the same memory to implement
    // both instances of "help", you are screwed...
    

    我猜这是一个病态的案例和/或垃圾进垃圾出(“医生,当我把头撞到墙上时很痛!”“那就不要这样做!”)......

    (p.s. 我只是提出这个问题——如果你觉得这篇文章混淆了水域,请适当评论,我会删除它)

    【讨论】:

    • 既然字符串修改是被禁止的,我想你也不能因为受它的影响就说其他代码错了。这就像说一个程序有错误,因为它可以通过利用另一个程序中的缓冲区溢出来执行。
    • 如果两个字符串存储在同一个地方,那么修改会影响两个字符串,并且比较仍然是相等的 - 或者你得到一个核心转储。当然,行为是未定义的;一切皆有可能 - 如果您愿意,请在 Google 上搜索“鼻恶魔”。
    • 执行此操作的程序格式错误,因此就您的程序而言,所有逻辑都到此结束。
    【解决方案3】:

    我可能会在 C 中写这样的东西(如果我经常使用 strncmp 并且不想进行字符计数):

    if(... strncmp(argv[i], "--help", sizeof("--help") - 1) == 0 
    

    【讨论】:

    • 但这会不必要地重复字符串两次。至少使用 (sizeof("--help") - 1)。是的,sizeof 在字符串文字上可以正常工作,因为它们的大小在编译时是已知的。
    • 另外,不,strlen 不计算空值。
    • 我不确定 sizeof 是否针对字符串文字。一般来说,我建议使用 C++ 和 std::string。 :-)
    • sizeof("--help") - 1 将匹配以 "--help" 开头的任何长度的字符串,而仅使用 sizeof("--help") 包括空终止符并且只会匹配“--help”。这似乎更有可能使用。
    【解决方案4】:

    正如其他人所说,strcmp() 与文字一起使用是完全安全的。如果你想使用strncmp(),试试这个:

    strncmp(argv[i], "--help", sizeof("--help"))
    

    让编译器帮你计算!

    这只会匹配确切的字符串“--help”。如果您想匹配以"--help" 开头的所有字符串(就像您的代码一样),请使用sizeof() - 1 不包括最后一个'\0'

    【讨论】:

    • 您的意思是 sizeof("--help") - 1,因为 sizeof 将包含空终止符。
    • @Evan:取决于你想做什么 - 已经编辑了我的答案;)
    • 那为什么首先使用 strncmp() 呢?更加冗长和多余。如果您只想匹配确切的字符串,只需使用 strcmp()。
    【解决方案5】:

    你是对的。

    此外,您提供的示例将匹配“--help”,还匹配以“--help”开头的所有内容(如“--help-me”)。

    过分热心 == 错误的罕见情况。

    【讨论】:

      【解决方案6】:

      这可能不是为了安全。可以只检查命令行参数的开始。许多程序只检查命令行开关的开头而忽略其余部分。

      【讨论】:

        【解决方案7】:

        是的,文字的存在将比较数据的大小限制为文字的大小。 stncmp 在这里是多余的。

        有些人可能会说 strncmp 是一个值得养成的好习惯,但这被计算字符的麻烦所抵消。

        【讨论】:

          【解决方案8】:

          据我所知,您是绝对正确的——没有理由使用 strncmp 代替 strcmp。也许人们只是过于谨慎(不一定是坏事)。

          【讨论】:

            【解决方案9】:

            是的,这是完全安全的,并且被认为是标准做法。 保证字符串文字正确地以 null 结尾。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-02-09
              • 1970-01-01
              • 2011-02-20
              • 1970-01-01
              • 2013-12-03
              • 1970-01-01
              • 1970-01-01
              • 2011-09-12
              相关资源
              最近更新 更多