所以这是我的代码中的一点,它给了我一些问题:
void childProcessHandler(string command){
int argCounter = 0;
for(int i=0; i!=command.size(); i++)
argCounter+=( command.at(i) == ' ');
char * temp, *token;
char *childArgs[argCounter];
argCounter = 1;
temp = new char [command.size()+1];
strcpy (temp, command.c_str());
token = strtok (temp," ");
childArgs[0] = token;
while (token!=NULL)
{
token = strtok(NULL," ");
childArgs[argCounter] = token;
argCounter++;
}
//delete[] temp; //Should remove token as well?
execvp(childArgs[0], childArgs);
cout<<"PROBLEM!"<<endl;
exit(-1);
}
在main()方法中,我的代码到达了forks()(父进程等待子进程退出)。然后子进程(进程ID == 0是?)调用方法childProcessHandler用户输入(命令运行+ args)作为参数。然后我标记用户输入并在其上调用execvp。
一切都在编译和执行。永远不会达到execvp之后的行,因为execvp仅在出现错误时才返回?
该项目是模拟一个unix终端,但是当我给它命令“date”时,没有任何东西被打印出来就像它应该......孩子退出并且父进程恢复正常然而没有任何东西被发送回终端窗口...
我做错了什么?
(我们也被“推荐”使用strtok来标记它,但如果有人有任何更简单的话,我愿意接受意见。)
谢谢!
例如,如果我输入“date”而不是“date”,则上述代码有效。我认为“tokenizer”可能会在childArgs []数组的末尾没有放置空字符。我会玩弄它并感谢您的快速反应!
(Ninja编辑,暂时还注释了删除[] temp)
答案 0 :(得分:2)
你正在混合std :: string和char / char *。很好,但你必须要小心,他们有不同的行为。
特别是这一行:
temp = new char [command.size()+1];
创建一个实际数组来保存字符串。
token = strtok (temp," ");
这使得令牌(它只是一个指针)指向临时内部的位置。 strtok()修改输入字符串以在字符串中创建一个临时字符串(听起来很疯狂,我知道)。
你需要复制字符串strtok()让你进入一个永久的家。使用std :: string来节省时间和代码,或者使用char *方式并自己分配新字符串。例如。而不是:
childArgs[0] = token;
你需要:
childArgs[0] = new char[strlen(token)+1];
strcpy(childArgs[0], token);
同样适用于在循环中通过命令参数存储在数组中的标记。
答案 1 :(得分:1)
你的childargs指针向量指向内存块“temp”中分配的字节。当你释放temp时,你正在移除childargs指针所指向的内存,可能会破坏你vector中的一些值。
删除对delete []的调用以停止释放childargs指针指向的内存。你不会泄漏记忆。一旦调用exec_ (),无论如何都会替换整个过程映像。调用exec _()(大部分)的唯一内容是你的文件描述符。
作为测试,尝试一些更简单的事情:在孩子中调用fork()之后,只需使用“date”路径调用exec。在摆弄参数列表向量之前做好工作。
作为另一项测试,请删除对exec的调用,并打印出整个指针向量,以确保您的令牌化工作方式符合您的预期。请记住,您的最终条目必须为NULL,以便您知道向量的结尾位置。