老实说,我不知道以下情况如何发生。这是代码:
while(1)
{
char** line = read_command();
char* command = line[0];
char** parameters = malloc(100);
int i;
for(i = 0; i < pNum; i++) // pNum is a global var containing the number of words read from read_command()
{
parameters[i] = line[i];
printf("%i: %s", i, parameters[i]);
}
printf("%s\n", parameters[0]);
parameters[0] = "/usr/bin/";
strcat(parameters[0], command);
printf("%s\n", command);
printf("%s\n", parameters[0]);
if(fork() != 0)
waitpid(1, &status, 0);
else
execve(parameters[0], parameters, NULL);
}
read_command()返回一个char **,它基本上是输入的字符串的“数组”,每个char *都包含一个单词。就像我进入“你好地球人”一样,结果将是[“你好”,“人”,“是”,“地球”]。这个功能总是有效的。
在第一次迭代时,一切都按预期工作。例如,当我输入“date”时,输出如下:
0: date
date
date
/usr/bin/date
and then the date is displayed
但是在第二次迭代时,如果我再次使用“date”作为输入,则输出如下:
0:date
edate
/usr/bin/datedate
and the date command is not issued
第二个printf语句总是在第一次迭代后打印“e”,即使我打印一个像“hello”这样的常量字符串。然后参数[0]以某种方式在其中有2个“日期”,即使命令指针只有1个“日期”。
在第三次迭代后,程序不等待用户输入,它只是循环不停,并显示“PM:警告,进程表已满!”
什么可能导致这种情况?
我在MINIX 3.1.0中使用cc编译器进行C
编辑: read_command():
char* line = malloc(), * linep = line;
size_t lenmax = 100, len = lenmax;
int c;
int currPos = 0;
int currParam = 0;
int i;
char** parameters = malloc(100);
if(line == NULL)
return NULL;
while(1)
{
c = fgetc(stdin);
if(c == EOF) || c == '\n')
break;
if(--len == 0)
{
char* linen = realloc(linep, lenmax *= 2);
len = lenmax;
if(linen == NULL)
{
free(linep);
return NULL;
}
line = linen + (line - linep);
linep = linen;
}
if((*line++ = c) == '\n')
break;
}
*line = '\0'; // everything up to this point i got from this link: http://stackoverflow.com/a/314422/509914
parameters[currentParam] = malloc(100);
for(i = 0; i < strlen(linep); i++);
{
if(isspace(linep[i]) || line[i] == EOF)
{
parameters[currParam][currPos] = '\0;
currPos = 0;
parameters[++currParam] = malloc(100);
}
else
parameters[currParam][currPos++] = line[i];
}
parameters[currParam][currPos] = '\0';
pNum = currParam + 1;
return parameters;
答案 0 :(得分:1)
有趣的是,那些通过阅读信誉良好的资源学习的人,例如几十年来经过考验的K&amp; R,往往比那些没有这些问题的人更频繁地解决这些问题...
char** parameters = malloc(100);
正在尝试分配100个字节。 realloc
行为相似,所以我再也不提这个了。也许你打算分配100批char *
?分配pNum
大量char *
:char **parameters = malloc(pNum * sizeof *parameters);
...... char* linen = realloc(linep, (lenmax *= 2) * sizeof *linep);
...
strcat
不分配内存;唯一分配内存的函数是malloc
,calloc
和realloc
。
当您致电strcat(foo, bar);
时,您要求strcat
将bar
指向的字符串附加到foo
指向的字符串末尾。在您的代码中,您正在尝试修改字符串文字。未定义的行为,通常是段错误。
即使您修改后的尝试也是错误的。在parameters[0] = "/usr/bin/";
中,您没有将字符串复制到parameters[0]
;你指定parameters[0]
指向字符串(通常在不可变的内存中,如前所述)。您真的需要通过创建MCVE来缩小未定义行为的来源......
在read_command()
函数char* line = malloc(), * linep = line;
的第一行,您调用malloc
而未提供参数。这是违反约束的行为。您的编译器应该向您发送错误。也许你忘记了#include <stdlib.h>
,所以malloc
遗漏了它的原型?请提供MCVE,这样我们就不必猜测。
if(c == EOF) || c == '\n')
还有另一个约束违规...即使我们填写空白为你制作MCVE(我们不应该这样做,因为这是你的工作和你要求我们提供帮助),这段代码无法编译。也许这就是造成你崩溃的原因? 始终检查编译器为您提供的消息。不要忽略警告......并且绝对不要忽略错误消息。
我将您声称来自this answer的代码进行了比较,结果完全不同。该答案的代码汇编为一个。尽管如此,这是你通过说谎来帮助你的人建立信任的方式吗?
你不需要那么多动态分配,通常我会尽我所能解释你如何以最好的方式做到这一点,但谎言让我失望。我还有一点要做:确保parameters
被空指针终止(类似于字符串如何被空字符终止),因为它需要{{ 3}}