I faced this problem in the below C++ program
#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;
}
Somehow this code fails with output:
MESSAGE
Errno value: 14
test: /tmp/tmp.9dU24JfFL4/main.cpp:17: void SetUpSlave(std::string): Assertion `false' failed.
This problem occurred on Ubuntu 24.04 with g++ 13.2.0.
if I change std::string(17, 'a');
to std::string(16, 'a');
, then the error disappears.
Also helps changing args_ptrs.reserve(args.size());
to args_ptrs.reserve(args.size() + 2);
3
execv
expects a null-terminated array of null-terminated strings, meaning the last const char*
element must be NULL
. Otherwise it has no way to tell how many arguments there are.
std::string::c_str()
would be more idiomatic for C code but as @john pointed out, data()
is also null-terminated.
void SetUpSlave(std::string path) {
std::vector<const char*> args_ptrs;
args_ptrs.reserve(args.size() + 1); // +1 for nullptr
for (int i = 0; i < args.size(); ++i) {
args_ptrs.push_back(args[i].c_str()()); // Null-terminated string
}
args_ptrs.push_back(nullptr); // Add null terminator to the array
execv(path.data(), args_ptrs.data());
cerr << "Errno value: " << errno << endl;
assert(false);
}
2