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 是吗?)使用用户输入(运行命令 + args)作为参数调用 childProcessHandler 方法。然后我对用户输入进行标记并对其调用 execvp。
一切都编译并执行。永远不会到达 execvp 之后的行,因为 execvp 仅在出现错误时返回,是吗?
该项目是模拟一个unix终端,但是当我给它命令“date”时,没有任何内容被打印出来...子进程退出并且父进程恢复得很好,但是没有任何内容被发送回终端窗口...
我做错了什么?
(此外,我们“建议”使用 strtok 来标记它,但如果有人有更简单的东西,我愿意接受意见。)
谢谢!
编辑
例如,如果我输入“date”而不是“date”,上面的代码就可以工作。我认为“tokenizer”没有在 childArgs[] 数组末尾放置空字符可能有些可疑。我会尝试一下并感谢您的快速回复!
(Ninja编辑,暂时也注释掉了delete[] temp)
So here is the bit of my code that's giving me problems:
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);
}
In the main() method my code gets to a point where it forks() (the parent process then waits for the child to exit.) then the child process (process ID == 0 yes?) calls the method childProcessHandler with the user input (command to run + args) as it's argument. Then I tokenize the user input and call execvp on it.
Everything compiles and executes. The line after execvp is never reached because execvp only returns when there is an error yes?
The project is to simulate a unix terminal however when I give it the command "date" nothing gets printed like it should... The child exits and the parent process resumes just fine however nothing is sent back up to the terminal window...
What am I doing wrong?
(Also we were "recommended" to use strtok to tokenize it but if anyone has anything simpler i'm open to opinions.)
THANKS!
EDIT
The above code works, for example, if I type in "date " instead of "date". I think there might be something fishy with the "tokenizer" not putting a null character at the end of the childArgs[] array. I'll play around with that and thanks for the quick responses!
(Ninja edit, also commented out delete[] temp for the time being)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您正在混合 std::string 和 char/char* 。好吧,但你必须小心,他们有不同的行为。
特别是这一行:
正在创建一个实际的数组来保存字符串。
这使令牌(这只是一个指针)指向 temp 内的一个位置。 strtok() 修改输入字符串以在字符串中创建临时字符串(我知道这听起来很疯狂)。
您需要将 strtok() 为您提供的字符串复制到永久的家中。要么使用 std::string 来节省时间和代码,要么使用 char* 方式并自己分配新字符串。例如,而不是:
您需要:
这同样适用于在命令参数循环期间存储在数组中的标记。
You're mixing std::string and char/char*. Fine, but you have to be careful, they have different behaviours.
In particular this line:
Is creating an actual array to hold a string in.
This is making token (which is just a pointer) point to a place inside temp. strtok() modifies the input string to make a temporary string within a string (sounds crazy, I know).
You need to copy the string strtok() gives you into a permanent home. Either use std::string to save you time and code, or do it the char* way and allocate the new string yourself. E.g. instead of:
you need:
The same applies to tokens stored in the array during the loop over the command arguments.
您的 childargs 指针向量指向内存块“temp”中分配的字节。当您释放 temp 时,您将删除 childargs 指针指向的内存,可能会损坏向量中的某些值。
删除对delete[]的调用以停止释放childargs指针指向的内存。你不会泄漏内存。一旦你调用 exec_() 你的整个进程图像无论如何都会被替换。调用 exec_() 后唯一幸存的东西(在大多数情况下)是文件描述符。
作为测试,尝试一些更简单的事情:在子进程中调用 fork() 后,只需使用“date”的路径调用 exec 即可。在摆弄参数列表向量之前先完成这项工作。
作为另一个测试,删除对 exec 的调用,并打印出整个指针向量,以确保您的标记化按照您认为应该的方式工作。请记住,您的最终条目必须为 NULL,以便您知道向量的末尾在哪里。
Your childargs vector of pointers point into the bytes allocated in the block of memory "temp". When you free temp, you are removing the memory pointed to by the childargs pointers, possibly corrupting some of the values within your vector.
Remove the call to delete[] to stop freeing the memory pointed to by the childargs pointers. You will not be leaking memory. Once you call exec_() your entire process image is replaced anyway. The only thing that survives a call to exec_() (for the most part) are your file descriptors.
As a test, try something a bit more simple: After your call to fork() in the child, just call exec with the path to "date". Make that work before fiddling with the parameter list vector.
As another test, remove your call to exec, and print out your entire vector of pointers to make sure that your tokenizing is working the way you think it should. Remember that your final entry must be NULL so that you know where the end of the vector is.