CentOS 7.5 和 Rocky Linux 8.4、Ubuntu 20.04 之间的不同 C++ fork() 行为
Different C++ fork() behavior between CentOS 7.5 & RockyLinux 8.4, Ubunu 20.04
我正在处理一些遗留代码。它在 CentOS 7 系统上运行良好。 args 数组在 Rocky 8.4 和 Ubuntu 20.04 系统上都被处理。我简化了问题并添加了打印语句。 execv() 正在启动另一个程序。进入 execv 的 args 搞砸了。如果没有 fork,代码将按预期工作。莫名其妙。
我有两个简单的测试程序,其中一个什么都不做。
test9.cpp
int main(){}
和test10.cpp
#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
int main()
{
std::vector<std::string> stringArgs;
std::string a{"./test9.x"};
std::string b{"test10.cpp"};
stringArgs.push_back(a);
stringArgs.push_back(b);
char* args[stringArgs.size()+1];
if(fork() == 0){
for(uint8_t i = 0; i < stringArgs.size(); i++) {
std::string tmp(stringArgs[i]);
args[i] = const_cast<char*>(tmp.c_str());
std::cout << "\n\t"<<args[i]<<"'\n\n";
}
std::cout << "\n\t"<<args[0]<<"'\n\n";
std::cout << "\n\t"<<args[1]<<"'\n\n";
// last argument has to be NULL
args[stringArgs.size()] = NULL;
execv(args[0],&args[0]);
std::cout << "\n\tERROR: Could not run '"<<args[0]<<"'\n\n";
}
else
std::cout<<"parent\n";
}
g++ -o test9.x test9.cpp; g++ -o test10.x test10.cpp
在 CentOS 7 上我得到:
$ ./test10.x
./test9.x
test10.cpp
./test9.x
test10.cpp
parent
在 Rocky Linux 8.4 和 Ubuntu 20.04 上我都明白了。注意 test9.x 在 for 循环后被 test10.cpp 替换。
./test10.x
parent
./test9.x
test10.cpp
test10.cpp
test10.cpp
ERROR: Could not run test10.cpp
这个循环
for(uint8_t i = 0; i < stringArgs.size(); i++) {
std::string tmp(stringArgs[i]);
args[i] = const_cast<char*>(tmp.c_str());
std::cout << "\n\t"<<args[i]<<"'\n\n";
}
正在创建指向堆栈上的临时指针的数组,或一些内部实现定义的 std::string
部分
改为这样做
for(uint8_t i = 0; i < stringArgs.size(); i++) {
args[i] = strdup(stringArgs[i]);
std::cout << "\n\t"<<args[i]<<"'\n\n";
}
我正在处理一些遗留代码。它在 CentOS 7 系统上运行良好。 args 数组在 Rocky 8.4 和 Ubuntu 20.04 系统上都被处理。我简化了问题并添加了打印语句。 execv() 正在启动另一个程序。进入 execv 的 args 搞砸了。如果没有 fork,代码将按预期工作。莫名其妙。
我有两个简单的测试程序,其中一个什么都不做。
test9.cpp
int main(){}
和test10.cpp
#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
int main()
{
std::vector<std::string> stringArgs;
std::string a{"./test9.x"};
std::string b{"test10.cpp"};
stringArgs.push_back(a);
stringArgs.push_back(b);
char* args[stringArgs.size()+1];
if(fork() == 0){
for(uint8_t i = 0; i < stringArgs.size(); i++) {
std::string tmp(stringArgs[i]);
args[i] = const_cast<char*>(tmp.c_str());
std::cout << "\n\t"<<args[i]<<"'\n\n";
}
std::cout << "\n\t"<<args[0]<<"'\n\n";
std::cout << "\n\t"<<args[1]<<"'\n\n";
// last argument has to be NULL
args[stringArgs.size()] = NULL;
execv(args[0],&args[0]);
std::cout << "\n\tERROR: Could not run '"<<args[0]<<"'\n\n";
}
else
std::cout<<"parent\n";
}
g++ -o test9.x test9.cpp; g++ -o test10.x test10.cpp
在 CentOS 7 上我得到:
$ ./test10.x
./test9.x
test10.cpp
./test9.x
test10.cpp
parent
在 Rocky Linux 8.4 和 Ubuntu 20.04 上我都明白了。注意 test9.x 在 for 循环后被 test10.cpp 替换。
./test10.x
parent
./test9.x
test10.cpp
test10.cpp
test10.cpp
ERROR: Could not run test10.cpp
这个循环
for(uint8_t i = 0; i < stringArgs.size(); i++) {
std::string tmp(stringArgs[i]);
args[i] = const_cast<char*>(tmp.c_str());
std::cout << "\n\t"<<args[i]<<"'\n\n";
}
正在创建指向堆栈上的临时指针的数组,或一些内部实现定义的 std::string
部分改为这样做
for(uint8_t i = 0; i < stringArgs.size(); i++) {
args[i] = strdup(stringArgs[i]);
std::cout << "\n\t"<<args[i]<<"'\n\n";
}