процесс, запущенный из c ++, иногда пропускает опцию - PullRequest
2 голосов
/ 18 июня 2020

ниже мой код, опция «--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 отсутствует при передаче ему?

1 Ответ

3 голосов
/ 18 июня 2020

Вы используете метод c_str временного строкового объекта ("--graph=" + conf.root()), который возвращает указатель на внутренний буфер этого строкового объекта, который больше не действителен после строки.

Вы можете использовать это вместо этого:

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

Эта строка не будет удалена до execvp, потому что переменная не будет go за пределами области видимости раньше.

Причина, по которой она иногда работала с недопустимым объектом в том, что возвращаемый указатель по-прежнему будет указывать на то место, где раньше находился буфер. Когда вы вызывали c_str, объект был все еще действителен, и даже если бы это было не так, вы все равно получили бы что-то от метода, обычно нет проверки против использования объектов после их уничтожения.

Если это буфер не перезаписывается между вызовом деструктора и использованием значения, старое значение будет прочитано, и, похоже, все работает. В зависимости от строковой реализации и размера строки буфер может находиться в куче или внутри самого строкового объекта (в стеке). В любом случае память можно было использовать повторно или нет. Вы используете отладчик, чтобы проверить, что на самом деле происходит в вашей системе, но любое изменение даже в несвязанных частях вашей программы, в стандартной библиотеке или компиляторе может изменить результат.

Ключевой концепцией C ++ является термин «неопределенное поведение». Это означает, что нет абсолютно никаких ограничений на то, что происходит в вашей программе при нарушении определенных условий. Это позволяет разработчикам языка (в основном компиляторам и стандартной библиотеке) производить оптимизацию, предполагая, что неопределенное поведение никогда не произойдет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...