【问题标题】:Unexpected output after the first iteration of this code [closed]此代码第一次迭代后的意外输出[关闭]
【发布时间】:2015-08-11 09:15:05
【问题描述】:

老实说,我真的不知道以下事情是如何发生的。代码如下:

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* 包含一个单词。就像我输入“hello people of earth”一样,结果将是 [“hello”、“people”、“of”、“earth”]。此功能始终有效。

在第一次迭代时,一切都按预期工作。例如,当我输入“日期”时,输出如下:

0: date
date
date
/usr/bin/date
and then the date is displayed

但在第二次迭代中,如果我再次使用“日期”作为输入,则输出如下:

0:date
edate 
/usr/bin/datedate 
and the date command is not issued

第二个 printf 语句在第一次迭代后总是打印“e”,即使我打印了一个像“hello”这样的常量字符串。然后参数 [0] 以某种方式在其中包含 2 个“日期”,即使命令指针只有 1 个“日期”。

并且在第三次迭代之后,程序不等待用户输入,它只是不停循环并显示“PM:警告,进程表已满!”

什么可能导致这种情况?

我在 MINIX 3.1.0 中使用 C 的 cc 编译器工作

编辑: 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;

【问题讨论】:

  • 您的printf("%i: %s", parameters[i]); 需要两个值,而不是一个。应该是:printf("%i: %s", i, parameters[i]);
  • char** parameters = malloc(100); 正在分配 100 个字节,而不是 100 块 char *。也许你的意思是char **parameters = malloc(pNum * sizeof *parameters);
  • @cdarke,谢谢,我改了。在我的代码中是正确的。
  • parameters[0] = strcat("/usr/bin/", command); 中,您告诉strcat 修改只读字符串文字"/usr/bin"... CRASH!
  • “它在我的代码中是正确的”——你为什么要发布除了你的代码之外的任何东西?当然,您不是手动输入所有这些,而是​​使用复制和粘贴?无论如何,您的代码充满了错误。

标签: c pointers fork minix execve


【解决方案1】:

有趣的是,那些通过阅读知名资源(例如几十年来久经考验的 K&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 不分配内存;唯一分配内存的函数是malloccallocrealloc

当您调用strcat(foo, bar); 时,您要求strcatbar 指向的字符串附加到foo 指向的字符串的末尾。在您的代码中,您正在尝试修改字符串文字。未定义的行为,通常是段错误。

即使您修改后的尝试也是错误的。在parameters[0] = "/usr/bin/"; 中,您没有将字符串 复制到parameters[0];;您正在分配 parameters[0] 指向字符串(正如我之前提到的,它通常位于不可变内存中)。您确实需要通过创建 MCVE 来缩小未定义行为的来源...

read_command() 函数char* line = malloc(), * linep = line; 的第一行中,您在没有提供参数的情况下调用了malloc。这是违反约束的。您的编译器应该向您发出错误。也许你忘记了#include &lt;stdlib.h&gt;,所以malloc 缺少它的原型?请提供一个 MCVE,这样我们就不必做这样的猜测了。

if(c == EOF) || c == '\n') 存在另一个约束违规...即使我们要填补空白为您生成 MCVE(我们不应该这样做,因为 这是你的工作 你在向我们寻求帮助),这段代码将无法编译。也许这就是导致您崩溃的原因? 始终检查编译器提供给您的消息。不要忽略警告...绝对不要忽略错误消息。

我对比了您声称来自this answer 的代码,结果完全不同。该答案的代码可以编译,例如。尽管如此,这是您与试图通过撒谎帮助您的人建立信任的方式吗?

您不需要这么多的动态分配,通常我会不厌其烦地解释如何以最好的方式做到这一点,但谎言让我望而却步。我还有一点要说明:确保parameters 被一个空指针终止(类似于字符串如何被一个空字符终止),因为它是the manual 所要求的。

【讨论】:

  • 唯一分配内存的函数包括callocalloca?
  • 好的,我把那部分改回了我第一次写的样子。我更改了它以试图找到错误。检查代码。问题仍然以完全相同的方式存在。 :-)
  • @ArmandMaree:你没抓住重点,“你第一次写它”可能也是错误的。如果你有一个指向文字的指针,那应该是constconst char * greet = "Hello";。千万不要错过const
  • @cdarke 糟糕,我忘了calloc...但我似乎在the C standard 中找不到关于alloca 的任何信息,所以也许是非 C 语言,因此与这个问题无关?
猜你喜欢
  • 2016-04-13
  • 1970-01-01
  • 1970-01-01
  • 2023-02-25
  • 1970-01-01
  • 2016-08-18
  • 1970-01-01
  • 2011-10-31
  • 1970-01-01
相关资源
最近更新 更多