Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么这段代码在一个平台上工作,但在另一个平台上不工作?_C++_Visual Studio Code_Boost_Visual Studio 2019_Centos8 - Fatal编程技术网

C++ 为什么这段代码在一个平台上工作,但在另一个平台上不工作?

C++ 为什么这段代码在一个平台上工作,但在另一个平台上不工作?,c++,visual-studio-code,boost,visual-studio-2019,centos8,C++,Visual Studio Code,Boost,Visual Studio 2019,Centos8,我在windows上编写了一个长而复杂的服务器程序。使用visual studio 2019 然后,我在vm virtualbox上创建了一个CentOS 8操作系统,并在那里传输了所有代码。并用可视化代码重建可执行文件。除了一个部分外,其他都可以 以下是导致崩溃的代码: //clients is std::map<int, boost::shared_ptr<Client>> clients; for (const auto& kv :

我在windows上编写了一个长而复杂的服务器程序。使用visual studio 2019

然后,我在vm virtualbox上创建了一个CentOS 8操作系统,并在那里传输了所有代码。并用可视化代码重建可执行文件。除了一个部分外,其他都可以

以下是导致崩溃的代码:

//clients is    std::map<int, boost::shared_ptr<Client>> clients;

        for (const auto& kv : clients) {
            
            int elapsed_seconds = boost::chrono::duration_cast<boost::chrono::seconds>(timeNow - kv.second->lastUpdated).count();

            int i = kv.first;

            if (elapsed_seconds >= ServerData::SessionTimeoutSeconds)
            {
                trash_bin.push_back(clients[i]);
                clients.erase(i);
            }
        }
所以,当for循环在从客户机中删除某些内容后进行迭代时,就会出现这个问题

问题是:

为什么它会自动解决这个问题,而不会中断windows上编译的代码的循环,但无法在centos 8上解决它

这将使用迭代器在范围内进行迭代。每次执行循环体后,迭代器将递增

这将使当前迭代器无效。当无效迭代器在循环体之后递增时,程序的行为是未定义的

为什么它能解决这个问题

因为当您在无效迭代器递增之前中断循环时,没有未定义的行为

这将使用迭代器在范围内进行迭代。每次执行循环体后,迭代器将递增

这将使当前迭代器无效。当无效迭代器在循环体之后递增时,程序的行为是未定义的

为什么它能解决这个问题


因为当您在无效迭代器递增之前中断循环时,没有未定义的行为。

我同意@eerorika。此外,您的break语句会跳出循环。如果没有它,循环将在if语句获得true条件后继续执行。那是一个非常不同的动作。您的循环是否打算一次只删除一个客户端?

我同意@eerorika的说法。此外,您的break语句会跳出循环。如果没有它,循环将在if语句获得true条件后继续执行。那是一个非常不同的动作。您的循环是否打算一次只删除一个客户端?

除非您只想删除第一个超时客户端,而不是更可能的所有超时客户端,否则代码中会有错误

这是你想要的吗

auto kv = clients.begin();
while (kv != clients.end()) {
    int elapsed_seconds = boost::chrono::duration_cast<boost::chrono::seconds>
                                     (timeNow - kv->second->lastUpdated).count();
    if (elapsed_seconds >= ServerData::SessionTimeoutSeconds) {
        trash_bin.push_back(*kv);
        kv = clients.erase(kv);
    }
    else
        ++kv;
}

除非您只想删除第一个超时客户端,而不是更可能的所有超时客户端,否则您的代码中会有一个bug

这是你想要的吗

auto kv = clients.begin();
while (kv != clients.end()) {
    int elapsed_seconds = boost::chrono::duration_cast<boost::chrono::seconds>
                                     (timeNow - kv->second->lastUpdated).count();
    if (elapsed_seconds >= ServerData::SessionTimeoutSeconds) {
        trash_bin.push_back(*kv);
        kv = clients.erase(kv);
    }
    else
        ++kv;
}


收集每个要擦除的元素,在for循环后从客户端擦除这些元素收集每个要擦除的元素,在for循环后从客户端擦除这些元素谢谢我的朋友。但我已经理解了这一部分。我想问的是,为什么在使用visual studio 2019在windows上编译代码时,即使我不使用break,它的工作方式也会有所不同;但在centos 8上使用可视化代码和g++不起作用。@uterian我已经告诉过你:程序的行为是未定义的。所以这不像不同的编译器处理循环的方式不同,只是随机的?@uterian它是未定义的行为。它不能保证是随机的。本课程的任何行为都不能保证。优秀且耐心地与课程理念对抗。做得好。这个实现是任何C++程序员必须实现的突破。谢谢我的朋友。但我已经理解了这一部分。我想问的是,为什么在使用visual studio 2019在windows上编译代码时,即使我不使用break,它的工作方式也会有所不同;但在centos 8上使用可视化代码和g++不起作用。@uterian我已经告诉过你:程序的行为是未定义的。所以这不像不同的编译器处理循环的方式不同,只是随机的?@uterian它是未定义的行为。它不能保证是随机的。本课程的任何行为都不能保证。优秀且耐心地与课程理念对抗。做得好。这个实现是任何C++程序员必须实现的突破性的。谢谢你,但是我问的不是它为什么会出错。我知道原因。但我不明白为什么它在不同的平台上表现不同。另外,不,该循环不应该一次只删除一个客户端。这一突破;这是一个短期的解决方案,如果需要的话,我会在以后替换整个代码。可能会有显著的实现差异。我怀疑您对擦除的调用可能会使随后重新访问的迭代器无效。实现上的差异可能决定了静默失败和崩溃之间的区别。我在精神上抓住了救命稻草,但我会用调试器来调查这种可能性。要意识到的重要一点是,即使在它似乎可以工作的平台上,它也可能工作10年,然后突然决定吃掉你的小狗并发射核导弹。[或者,更现实地说,会导致无声数据损坏,您只有在重写备份后才会注意到这一点]谢谢您,但我想问的不是为什么会出现错误。我知道原因。但我不下手
为什么它在不同的平台上表现不同。另外,不,该循环不应该一次只删除一个客户端。这一突破;这是一个短期的解决方案,如果需要的话,我会在以后替换整个代码。可能会有显著的实现差异。我怀疑您对擦除的调用可能会使随后重新访问的迭代器无效。实现上的差异可能决定了静默失败和崩溃之间的区别。我在精神上抓住了救命稻草,但我会用调试器来调查这种可能性。要意识到的重要一点是,即使在它似乎可以工作的平台上,它也可能工作10年,然后突然决定吃掉你的小狗并发射核导弹。[或者,更现实地说,导致只有在重写备份后才会注意到的无声数据损坏]或者使用std::erase_if@eerorika是的,如果你有C++ 20编译器,或者使用STD::if@eerorika是的,如果你有一个C++ 20编译器。
int i = kv.first;
clients.erase(i);
 break;//this line makes it work.
auto kv = clients.begin();
while (kv != clients.end()) {
    int elapsed_seconds = boost::chrono::duration_cast<boost::chrono::seconds>
                                     (timeNow - kv->second->lastUpdated).count();
    if (elapsed_seconds >= ServerData::SessionTimeoutSeconds) {
        trash_bin.push_back(*kv);
        kv = clients.erase(kv);
    }
    else
        ++kv;
}