gpt4 book ai didi

c - 写一个 shell 。使用管道执行命令时为 "uninitialised byte(s)"

转载 作者:行者123 更新时间:2023-11-30 18:00:44 24 4
gpt4 key购买 nike

我正在尝试用 C 语言编写自己的 shell。下面的代码适用于没有管道的命令,但不适用于其他情况。

使用 --trace-children=yes 和 --track-origins=yes 运行 valgrind 会给出“Syscall param execve(argv) point to uninitialized byte(s)”(请参阅​​下面的完整错误)。

在相关方法中(参见下面的 makeargs),valgrind 告诉我“未初始化的值是由堆分配创建的”,在这一行“argv = (char *)malloc((count+1) * sizeof(char*));"

使用我的“ls | sort”测试输入,valgrind 表示“已分配大小为 12 的 block ”。我不明白这是怎么可能的,因为 ls 和 sort 每个都会​​调用 makeargs 并且都应该分配 8 个字节,因为应该有 4 个字节用于 char*,然后 4 个字节用于 execvp 最后需要的 (char*)NULL参数数组的。

执行此命令后程序挂起。

我不确定为什么会发生这种情况,因为如果只有一次 makeargs 调用(无管道),它就会起作用。任何意见将不胜感激。

void execCommand(char** commandParts, int pipeCount)
{
const int PIPE_READ = 0;
const int PIPE_WRITE = 1;
int numCommands = pipeCount + 1;
int newfds[2];
int oldfds[2];

int k = 0;
for(k; k < numCommands; k++)
{

//more commands exist
if(k < pipeCount)
{
if (pipe(newfds) == -1)
{
perror("new pipe error");
exit(EXIT_FAILURE);
}
}

if(fork() == 0) //child
{
//is prev command
if(k > 0)
{
dup2(oldfds[PIPE_READ], STDIN_FILENO);
close(oldfds[PIPE_READ]);
close(oldfds[PIPE_WRITE]);
}

//more commands exist
if(k < pipeCount)
{
close(newfds[PIPE_READ]);
dup2(newfds[PIPE_WRITE], STDOUT_FILENO);
close(newfds[PIPE_WRITE]);
}
char** args = NULL;
int argcount = makeargs(commandParts[k], &args);

if(execvp(args[0], args) == -1)
{
printf("%s: command not found \n", args[0]);
}
}
else //parent
{
int status;
waitpid(-1, &status, NULL);

//is prev command
if(k > 0)
{
close(oldfds[PIPE_READ]);
close(oldfds[PIPE_WRITE]);
}
//more commands exist
if(k < pipeCount)
{
oldfds[PIPE_READ] = newfds[PIPE_READ];
oldfds[PIPE_WRITE] = newfds[PIPE_WRITE];
}
}
//there are pipes
if(pipeCount > 0 && k > 0)
{
close(newfds[PIPE_READ]);
close(newfds[PIPE_WRITE]);
}
// if(argcount > 0)
// cleanArgs(argcount, args);
}
}

被调用的 make args 方法

int makeargs(char *s, char *** argv)
{
stripLeadingAndTrailingSpaces(s);
int k =0, count = 0;
for(k; k < strlen(s); k++)
{
if(s[k] == ' ')
count++;
}
count++;

char* parts = strtok (s," ");
strip(parts);

*argv = (char **)malloc((count+1) * sizeof(char*));

(*argv)[0] = (char *)malloc(strlen(parts)+1);
strcpy((*argv)[0], parts);

int i = 1;
for(i; i < count; i++)
{
parts = strtok (NULL, " ");
if(parts != NULL)
{
strip(parts);
(*argv)[i] = (char *)malloc(strlen(parts)+1);
strcpy((*argv)[i], parts);
}
}
(*argv)[count] = NULL;

return count;
}

valgrind 输出

==3603== Syscall param execve(argv) points to uninitialised byte(s)
==3603== at 0x40E2CDF: execve (execve.c:60)
==3603== by 0x40E314E: execvp (execvp.c:30)
==3603== by 0x8049069: main (cscd340_s12_hw2.c:250)
==3603== Address 0x41c617c is 4 bytes inside a block of size 12 alloc'd
==3603== at 0x4028876: malloc (vg_replace_malloc.c:236)
==3603== by 0x8049416: makeargs (ush.c:100)
==3603== by 0x8048E61: execCommand (cscd340_s12_hw2.c:191)
==3603== by 0x8049069: main (cscd340_s12_hw2.c:250)
==3603== Uninitialised value was created by a heap allocation
==3603== at 0x4028876: malloc (vg_replace_malloc.c:236)
==3603== by 0x8049416: makeargs (ush.c:100)
==3603== by 0x8048E61: execCommand (cscd340_s12_hw2.c:191)
==3603== by 0x8049069: main (cscd340_s12_hw2.c:250)

最佳答案

你有一些错误的计数:count是空格的数量,而不是命令行中的单词的数量。这会影响复制代码:

for(i; i < count; i++)
{
parts = strtok (NULL, " ");
if(parts != NULL)
{
...
}
}

如果输入命令行中的单词太少,argv 中的一些尾随条目将无法初始化。您可能想做这样的事情:

for(i; i <= count; i++)
{
parts = strtok (NULL, " ");
if(parts != NULL)
{
... // consider using strdup
}
else
{
(*argv)[i] = NULL;
break;
}
}

关于c - 写一个 shell 。使用管道执行命令时为 "uninitialised byte(s)",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10265089/

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