与execvp()有问题

时间:2011-09-29 20:02:21

标签: c++ fork execvp

所以这是我的代码中的一点,它给了我一些问题:

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)

2 个答案:

答案 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,以便您知道向量的结尾位置。