gpt4 book ai didi

c - execvp() 函数总是返回一个负值

转载 作者:太空宇宙 更新时间:2023-11-04 06:56:18 26 4
gpt4 key购买 nike

我正在编写一个模拟 shell 程序,用于使用 Linux 命令函数 execvp() 练习 C。我知道每当返回值小于 0 时,执行在 execvp 中传递的命令时就会出错。我对我的 stringTok() 函数处理语句字符数组持肯定态度正确传递,因为我打印了它们的长度和字符串值以进行双重检查。对于句子的最后一个记号,它本质上是将参数列表分成单独的记号,我将 '\0' 字符分配给该记号的最后一个字符。
最终,在 stringTok() 中将每个单独的标记分配给 char*cmdargv[MAX_LINE]execvp(cmdargv[0], cmdargv) 是我传递命令参数的方式。例如,“ls -al”是输入,fgets() 函数将该字符串读入 args[MAX_LINE]。子进程将运行 execvp,但会返回一个负值并打印出错误字符串。这甚至不起作用,因为我尝试手动将值分配给代码中注释的 cmd 和 argv。我想我一定是在 execvp() 中传递了错误的值或者做错了什么。
理想情况下,如果我输入“ls -al”,它应该和在 linux shell 中完全一样,列出当前目录中的所有文件或目录(预期输出)。

输入:
奥什>ls -al
输出:
参数:长度 2
内容:ls
最后一个元素 115
长度 3
内容:-al
最后一个元素 108
最后一位成员:(null)
osh>错误::地址错误
最后一位成员:(null)
奥什>

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>

#define MAX_LINE 80


int stringTok(char* sentence, char** tokens) {

const char* delim = " \r\n";
int count = 0;

// make copy of sentence for strtok
size_t len = strlen(sentence);
char *copy = malloc(len+1);
if(!copy) return 0; // if copy null, return 0
strncpy(copy, sentence, len);

copy[len] = '\0';

// Allocate and copy tokens
for(char* word = strtok(copy, delim);
word;
word = strtok(NULL, delim))
{
size_t len = strlen(word);
tokens[count] = malloc(len+1);
if(!tokens[count]) break;
strncpy(tokens[count], word, len);
tokens[count][len] = '\0';
count++;
}
size_t strlenth = strlen(tokens[count - 1]);
//if(count > 1) {
// tokens[count - 1][strlenth -1] = '\0';
//}
tokens[count] = NULL;
return count;
}

int main(void) {
char args[MAX_LINE]; // command to be executed
char *cmdargv[MAX_LINE]; // command tokens

int should_run = 1;

do {
printf("osh>");
fflush(stdout);
fgets(args, MAX_LINE, stdin);
//fflush(stdout);

printf("args:<%s>\n", args);

int count = stringTok(args, cmdargv);
for(int i = 0; i < count; i++) {
printf("len %ld\n", strlen(cmdargv[i]));
printf("content: %s\n", cmdargv[i]);
printf("last elememnt %d\n", cmdargv[i][strlen(cmdargv[i]) - 1]);
}
cmdargv[count] = NULL;
printf("last member:%s", cmdargv[count]);
//printf("cmdargv:%s\n", cmdargv[0]);
//printf("cmdargc:%d\n", cmdargv[0][strlen(cmdargv[0]) - 1]);
int pid = fork();

char *cmd = "ls";
char *argv[3];
argv[0] = "ls";
argv[1] = "-la";

if(pid == 0) {
execvp(cmd, argv);
if(execvp(cmd, argv) < 0) {
//printf("Error Executing Command\n");
perror("Error:");
}
} else if (pid > 0) {
// if '&' {
// wait(&pid)
//}
} else {
printf("Fork failed\n");
exit(1);
}
printf("\n");
} while(should_run);
return 0;
}

最佳答案

The execv(), execvp(), and execvpe() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers must be terminated by a null pointer

由于数组在 C 中就像指针一样传递,并且没有隐藏的方法让被调用函数知道数组的长度,因此必须显式给出。在单独的参数中(例如,fgets()size 参数),或以已知值结尾的数组,如 NULL (如此处的 execv*)。您的代码没有将最终参数设置为 NULL,这可能会导致 execlp 返回错误地址错误或类似错误,因为您设置的值之后的未初始化值将是被当作​​指针,很可能指向无效的内存地址。

解决这个问题让 exec 在这里为我工作。

此外,您应该使用类似 perror() 的方法来获取有关什么 错误发生的信息,而不是常量错误消息。如果 exec 失败,子进程将继续运行,因此使用 _exit() 终止它。

关于c - execvp() 函数总是返回一个负值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44012147/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com