在 for 循环的某些迭代中字符串的长度为 0,而在其他迭代中则不是

Length of string is 0 on some iterations of for-loop and not others

我正在使用 nlohmann::json C++ 库。我有以下代码。

#include <iostream>
#include <json.hpp>

using json = nlohmann::json;

int main(){
    json m;
    m["aaaaaaaa"] = 0;
    m["bbbbbbbbbbbbb"] = 0;
    m["ccccccccccccccccccc"] = 0;
    m["dddddddddddddddddd"] = 0;
    m["eeeeeeeeeeeeeeeeee"] = 0;
    m["fffffffffffff"] = 0;
    m["gggggggggggg"] = 0;
    m["hhhhhhhhhhhh"] = 0;
    m["iiii"] = 0;
    m["jjjjjjjjjjjjjjj"] = 0;
    m["kkkkkkkkkkkkkk"] = 0;
    m["llllllllllllllll"] = 0;

    for (int i = 0; i < 100; i++) {
        const char* mstr = m.dump().c_str();
        std::cout << strlen(mstr) << std::endl;
    }

}

我希望 for 循环的所有 100 次迭代的输出 strlen(mstr) 完全相同。

在某些运行中,我得到了预期的输出。

223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 程序以退出代码结束:0

但在其他运行中,我偶尔会看到字符串的长度为 0。

223 0 223 223 223 223 223 223 223 223 223 0 223 223 223 223 223 0 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 0 223 223 223 223 223 223 223 223 0 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 223 程序以退出代码结束:0

这怎么可能发生?

转储函数 returns 一个对象到 stack.By 使用此对象的指针,您可能偶尔会发现对象内存在打印值之前被重用。应该做的是直接存储转储的字符串:

std::string mstr = m.dump();
std::cout << mstr.size() << std::endl;

m.dump() returns 临时 string_t 对象。当到达整个 const char* mstr = m.dump().c_str(); 表达式末尾的 ; 时,该临时对象超出范围。这意味着当您在其上调用 c_str() 时该对象仍然存在,但是在您将 char* 指针保存到 mstr 之后但在您将其打印到 [=20= 之前它被销毁了].指针在那一点悬空,所以输出的行为是 undefined.

您需要保存临时对象,以便在使用指向它的指针完成操作之前保持数据有效,例如:

for (int i = 0; i < 100; i++) {
    string_t mstr = m.dump();
    std::cout << strlen(mstr.c_str()) << std::endl;
}

然后可以简化,因为在这种情况下您实际上根本不需要使用 strlen(),C++ 字符串知道自己的长度:

for (int i = 0; i < 100; i++) {
    string_t mstr = m.dump();
    std::cout << mstr.size() << std::endl;
}

或者,您可以在临时对象仍在范围内时打印 size()

for (int i = 0; i < 100; i++) {
    std::cout << m.dump().size() << std::endl;
}