【问题标题】:While loop hangs program after valid input is entered?输入有效输入后,while循环会挂起程序吗?
【发布时间】:2012-12-01 17:31:03
【问题描述】:

自昨晚以来,我一直被这个问题困扰着,我希望第二双新的眼睛会有所帮助。

问题是,如果在userIn 函数中输入了无效的输入(任何不是 1-99 之间的数字),main 中 while 循环结束时的测试 printf 将打印“ERR = 1 ",while 循环并再次调用 userIn。到目前为止一切顺利,但是当输入有效输入时,while 循环结束时的测试 printf 会打印“ERR = 0”,然后程序挂起。测试 printf 说“HELLO”永远不会被打印出来。

任何关于为什么的建议都非常受欢迎。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

void userIn (int *x)
    {
    char b;
    printf("Please enter a new value for Vm: ");
    scanf(" %i",x);
    while (((b=getchar())!='\n')&&(b!=EOF));
    return; 
    }
int main (void)
    {
    int  fd, x, err;
    char *npipe = "/tmp/fms",
         input[3];
    struct stat info;
    printf("\n");

    //get user input
    err = 1;
    while (err)
        {
        userIn(&x);
        if (x > 0 && x < 100) err = 0;
        //else printf("\033[1A\033[K");

        printf("ERR = %i\n",err);//TEST PRINTF
        }
    printf("HELLO");//TEST PRINTF

    //if pipe exists
    if ( (!lstat(npipe,&info)) && (S_ISFIFO(info.st_mode)) )
        {
        sprintf(input,"%i",x);
        //write user input to named pipe created by 'parent.c'
        fd = open(npipe, O_WRONLY);
        write(fd, input, sizeof(input));
        close(fd);
        }
    else printf("\033[0;31mNamed pipe doesn't exist, %i not passed.\n\n\033[0m",x);
    return 0;
    }

【问题讨论】:

    标签: c while-loop freeze


    【解决方案1】:

    如果我在我的系统上运行您的代码,输出如下所示:

    Please enter a new value for Vm: 101
    ERR = 1
    Please enter a new value for Vm: 1
    ERR = 0
    HELLONamed pipe doesn't exist, 1 not passed.
    

    也就是说,循环在您认为应该退出的时候准确地退出。当然,代码会立即退出,因为我的系统上不存在/tmp/fms

    但是,如果我创建 /tmp/fms,那么我会看到:

    Please enter a new value for Vm: 1
    ERR = 0
    

    ...并且没有额外的输出。这是因为printf 语句的输出被缓冲,并且对命名管道的写入被阻塞,所以输出永远不会被刷新。在您的 printf 中添加 \n 可能会如您所愿地显示它。

    【讨论】:

    • 顺便说一句,gdbstrace 都可以成为准确确定代码挂起位置的好工具。
    • 当程序自行运行时,您的第一个输出是我所期望的。从您所说的来看,当它自己运行时以及从父程序执行分叉时,它会阻止写入管道。这可能是因为当父程序完成时我没有正确删除管道所以我试图访问旧管道?我目前正在使用 unlink()。
    • 还将调查gdbstrace,为指出他们而欢呼。
    • 废掉第二个问题,刚刚重新阅读管道上的man文件,为正确方向的指针欢呼。
    • 万一其他人读过这个问题......我对管道的写入被阻塞,因为我不是同时在管道上分别执行写入和读取操作。一旦我从父程序中删除了wait(),一切都按预期工作。
    【解决方案2】:

    与您的直觉相反,程序在printf("HELLO"); 行之后 冻结。由于您在该 printf 中没有换行符,HELLO 被缓冲并且不会立即刷新到终端。

    是否有从你的管道另一端读取的进程?

    【讨论】:

    • 是的,当这个程序是从另一个进程分叉执行时。但是,如果程序自己运行并且管道不存在,程序仍然应该优雅地退出,因为 larsks 在他的机器上没有使用管道
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-18
    • 1970-01-01
    • 2019-03-19
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 2013-11-16
    相关资源
    最近更新 更多