代码之家  ›  专栏  ›  技术社区  ›  rptony

std::string连接的运行时依赖项

  •  1
  • rptony  · 技术社区  · 16 年前
    std::string sAttr("");
    sAttr = sAttr+VAL_TAG_OPEN+sVal->c_str()+VAL_TAG_CLOSE;
    

    我在代码中定义的其他位置

    const char VAL_TAG_OPEN[]   = "<value>";
    

    sVal 是从字符串指针数组中检索到的变量。这在大多数系统、Windows和Linux中都可以正常工作。然而,在一个客户网站上,据我所知有一个Linux版本,我们在该版本上做了一些广泛的测试,产生了一个结果,好像我从未使用过 VAL_TAG_OPEN VAL_TAG_CLOSE . 我收到的结果是

    sAttr = sAttr+sVal->c_str();
    

    怎么回事?.Std::字符串连接是否随运行时的不同而变化?

    4 回复  |  直到 16 年前
        1
  •  2
  •   fbonnet    16 年前

    为什么 ->c_str() ?如果 sVal 是一个 std::string ,尝试删除此呼叫。请记住,计算顺序是未定义的,因此您可能最终会添加指针而不是连接字符串,因为 VAL_TAG_OPEN , sVal->c_str() VAL_TAG_CLOSE 都是普通的C字符串。我建议你使用加法赋值运算符 += ,例如:

    sAttr += VAL_TAG_OPEN;
    sAttr += *sVal; /* sVal->c_str() ? */
    sAttr += VAL_TAG_CLOSE;
    

    (无论如何应该更快)。

        2
  •  1
  •   gimpf    16 年前

    不,std::字符串连接绝对不应该依赖于运行时,但无论如何 VAL_TAG_OPEN VAL_TAG_CLOSE 似乎是空字符串。

    我猜您在某个地方有某种缓冲区溢出或无效的指针算术,所以您的程序会覆盖包含那些“常量”值的内存。无论您的内存最终在哪里,都是运行时(因此是操作系统版本)特有的。在过去,通过切换编译器或优化器选项,我被类似的事情困住了。

    正如您提到的在原始数组中保留指向std::string实例的原始指针,这样的错误并非完全不可能,但可能很难检测到,因为使用调试构建不会给您任何迭代器检查所有这些都是原始的东西…祝你好运。

        3
  •  1
  •   rptony    16 年前

    我不认为这是导致问题的评估顺序。这是因为在开始和结束时都有常量char数组

    const char VAL_TAG_OPEN[]   = "<value>";
    const char VAL_TAG_CLOSE[]  = "</value>"
    

    串联运算符认为val_tag_opn和val_tag_不是空终止符字符串。因此,优化器只是忽略了他们认为它是垃圾。

    sAttr += std::string(VAL_TAG_OPEN);
    sAttr += *sVal;
    sAttr += std::string(VAL_TAG_CLOSE);
    

    这确实解决了问题。

        4
  •  0
  •   17 of 26    16 年前
    sAttr = sAttr+VAL_TAG_OPEN+sVal->c_str()+VAL_TAG_CLOSE;
    

    正如FBONNET所说,这是一个评估问题的顺序。

    如果严格从左到右对该行进行计算,则每个加法的结果是一个std::string对象,该对象有一个用于加法的运算符重载,并且按预期工作。

    如果没有从左到右进行评估,那么你最终会把指针加在一起,谁知道这会给你带来什么。

    避免这个构造,只需在std::string上使用+=操作符。