下面是我的代码,即使在同一台计算机上,选项“--graph”也被错过了一段时间。

boost::filesystem::path cmd =
            boost::filesystem::path(my::Cmdline::get_workspace())
            / "bin" / "cmdbin";

char const *argv[1024] = {};
int idx = 0;
argv[idx++] = cmd.c_str();
argv[idx++] = ("--graph=" + conf.root()).c_str();
argv[idx++] = "--file=/home/cmd/cmd.pid";
argv[idx++] = "--logfile=/home/cmd/cmd.log";


_exit(execvp(argv[0], (char **)argv));
// ps aux and grep the process

root     25323  4.3  0.0 1370872 10720 ?       S<l  17:11   0:00 /home/cmd/cmdbin --logfile=/home/cmd/cmd.log --file=/home/cmd/cmd.pid


// which should be

root     25323  4.3  0.0 1370872 10720 ?       S<l  17:11   0:00 /home/cmd/cmdbin --graph=/home/cmd --file=/home/cmd/cmd.pid --logfile=/home/cmd/cmd.log


顺便说一句,“conf.root()”是一个内联函数;它与execvp有关吗? argv放弃时会丢失吗?

最佳答案

您正在使用临时字符串对象c_str("--graph=" + conf.root())方法,该方法返回指向该字符串对象的内部缓冲区的指针,该指针在行后不再有效。

您可以改用以下方法:

std::string graph_option = "--graph=" + conf.root();
argv[idx++] = graph_option.c_str();

该字符串不会在execvp之前删除,因为该变量不会在范围之前。

有时它与无效对象一起工作的原因是返回的指针仍将指向缓冲区原来所在的位置。当您调用c_str时,对象仍然有效,即使不是,您仍然可以从该方法中得到一些东西,通常在对象被销毁后不会检查使用对象。

如果在析构函数调用和使用该值之间碰巧不覆盖该缓冲区,则将读取旧值,并且一切似乎正常。根据字符串的实现和字符串的大小,缓冲区可能位于堆中,也可能位于字符串对象本身(位于堆栈中)内。无论哪种方式,内存都可以被重用。您可以使用调试器检查系统上实际发生的情况,但是即使对程序的不相关部分,标准库或编译器进行任何更改,都可能会改变结果。

C++中的一个关键概念是“未定义的行为”一词。这意味着,如果违反某些条件,对程序中发生的事情绝对没有限制。这使得该语言的实现者(主要是编译器和标准库)可以进行优化,前提是从未发生未定义的行为。

关于c++ - 从c++运行的过程有时会丢失选项,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/62446914/

10-10 21:19