为什么系统调用在循环的第二次迭代时崩溃,而在第一次迭代时成功?

问题描述 投票:0回答:1

我在c++程序中遇到这个问题

#include <bits/stdc++.h>
#include <unistd.h>
#include <sys/wait.h>

using namespace std;

std::vector<std::string> args;

void SetUpSlave(std::string path) {
    std::vector<char*> args_ptrs;
    args_ptrs.reserve(args.size());
    for (int i = 0; i < args.size(); ++i) {
        args_ptrs.push_back(args[i].data());
    }
    execv(path.data(), args_ptrs.data());
    cerr << "Errno value: " << errno << endl;
    assert(false);
}

int main() {
    int status;
    for (int i = 0; i < 2; ++i) {
        args = { "/usr/bin/echo", "MESSAGE" };
        pid_t slave_pid = fork();
        if (slave_pid) {
            assert(waitpid(slave_pid, &status, 0) != -1);
        } else {
            SetUpSlave("/usr/bin/echo");
        }
        std::string(17, 'a');
    }
    return 0;
}


为什么这段代码会失败并输出:

MESSAGE
Errno value: 14
test: /tmp/tmp.9dU24JfFL4/main.cpp:17: void SetUpSlave(std::string): Assertion `false' failed.

此问题发生在 ubuntu 24.04 和 g++ 13.2.0 上

如果我改变 std::string(17, 'a');到 std::string(16, 'a');错误消失。

还有助于更改 args_ptrs.reserve(args.size());到 args_ptrs.reserve(args.size() + 2);

c++ linux exec system-calls
1个回答
0
投票

execv
需要一个以 null 结尾的字符串数组,这意味着最后一个
char*
元素是
NULL

您应该使用

std::string::c_str()
,而不是
data()
,因为前者是空终止的。

void SetUpSlave(std::string path) {
    std::vector<char*> args_ptrs;
    args_ptrs.reserve(args.size()+1);
    for (int i = 0; i < args.size(); ++i) {
        args_ptrs.push_back(args[i].c_str()());
    }
    args_ptrs.push_back(nullptr); // Add null termination
    execv(path.data(), args_ptrs.data());
    cerr << "Errno value: " << errno << endl;
    assert(false);
}
© www.soinside.com 2019 - 2024. All rights reserved.