【问题标题】:While Loop Terminating Unexpectedly (C/C++)While 循环意外终止 (C/C++)
【发布时间】:2013-07-30 06:40:11
【问题描述】:

我根本不知道出了什么问题。我有一个 while 循环(代码块 1),它在循环的一次迭代后立即终止。我什至注释掉了整个 switch 语句,所以只剩下printf(...)scanf(...),循环似乎终止了。

循环:

int main(int argc, char *argv[]) {
if(argc != 2) {
    printf("Usage requires hostname\n");
    return 1;
}

TCPClient client;
char str[1];
unsigned char buf[BUFLEN];
bool run = true;

printf("The commands in use are:\n"
    "h - help\n"
    "r - read ENCs (incremental)\n"
    "x - exit\n");

while(run) {
    printf("Enter a command: ");
    scanf("%s", str);

    switch(str[0]) {
      case 'h':
        printf("The commands in use are:\n"
            "h - help\n"
            "r - read ENCs (incremental)\n"
            "x - exit\n");
        break;

      case 'r':
        client.recvData(argv[1], buf, BUFLEN);

        for(int i = 0; i < BUFLEN / 4; i++) {
            if(i % 3 == 0)
                printf("\n");

            printf("Encoder %d: %d\t", i, (int)((((buf[4 * i] << 24) | (buf[4 * i + 1] << 16)) | (buf[4 * i + 2] << 8)) | (buf[4 * i + 3])));
        }
        printf("\n");
        break;

      case 'x':
        run = false;
        break;

      default:
        printf("Unrecognized command\n");
        break;
    }
}

return 0;
}

在某一时刻,我添加了

if(run)
    printf("run = true");

在 while 循环之后查看它是否由于控制布尔 (run) 为假而中断。结果是没有输出,表明不知何故,run 变成了假。无论输入是什么,或者即使 switch 语句消失,都会发生这种情况,在这种情况下,任何事情都不应该使 run 变为 false。

真正奇怪的是,在另一个文件中,我有一个类似的循环,但它确实有效:

void *control(void *arg) {
DAC dac(5);
char str[1];
int chan = -1;
uint16_t code = -1;

while(run) {
    printf("Enter a command: ");
    scanf("%s", str);

    switch(str[0]) {
      case 'h':
        printf("The commands in use are:\n"
            "h - help\n"
            "s - set DACs\n"
            "r - read ENCs (incremental)\n"
            "t - read ENCs (cumulative)\n"
            "q - Toggle the quadrature waveform\n"
            "x - exit\n");
        break;

      case 's':
        chan = code = -1;

        printf("Enter the DAC channel: ");
        scanf("%d", &chan);

        printf("Enter the value: ");
        scanf("%hu", &code);

        pthread_mutex_lock(&lock);
        dac.setDAC(chan, code);
        pthread_mutex_unlock(&lock);
        break;

      case 'r':
        pthread_mutex_lock(&lock);
        for(int i = 0; i < BUFLEN; i++) {
            if(i % 3 == 0)
                printf("\n");
            printf("Encoder %d: %d\t", i, incBuf[i]);
            incBuf[i] = 0;
        }
        printf("\n");

        pthread_mutex_unlock(&lock);
        break;

      case 't':
        pthread_mutex_lock(&lock);
        for(int i = 0; i < BUFLEN; i++) {
            if(i % 3 == 0)
                printf("\n");
            printf("Encoder %d: %ld\t", i, cumBuf[i]);
        }
        printf("\n");

        pthread_mutex_unlock(&lock);
        break;

      case 'q':
        runSignal = !runSignal;
        if(runSignal)
            printf("Quadrature waveform enabled\n");
        else
            printf("Quadrature waveform disabled\n");

        break;

      case 'x':
        run = false;
        break;

      default:
        printf("Unrecognized command\n");
        break;
    }
}

dac.reset();
pthread_exit(NULL);
}

我对正在发生的事情感到很迷茫......

【问题讨论】:

  • 这是很明显的事情,但我必须问一下以防万一——你实际上是在为程序提供参数,不是吗?
  • 是的,我愿意。无论哪种方式,如果我不这样做,程序就会退出。顶部的检查确保了这一点。

标签: c++ loops while-loop break


【解决方案1】:

在 while 循环中 scanf("%s", str); 是错误的,因为 str[] 的声明是 char str[1]; 它只能存储一个字符(因为大小为 1)。但是scanf() 至少存储两个字符(包括\0)。 假设如果您仅输入c,它的存储为"c",它由两个字符组成,第一个是c,第二个是\0,这会导致缓冲区溢出——根据C 标准的未定义行为。

【讨论】:

  • 有趣。为什么它在后一种情况下(工作代码)有效,但在前一种情况下无效?在后一种情况下,缓冲区是否只是简单地溢出到其他东西中?无论如何,将声明更改为char str[2] 修复了它。谢谢。
  • @HariGanti 是未定义的行为,它不能保证它会一直工作,实际上在最坏的情况下它会工作。
  • 将其固定到 str[2] 是不够的。流氓用户只需输入一个包含两个字符的字符串,就会出现同样的错误。
  • @MartinRichtarsky 是的!其实scanf()它自己并不安全!
  • @MartinRichtarsky,虽然这是真的,但我是唯一一个使用它的人,它主要是一个测试程序。此外,您的论点对于任何字符串长度都是正确的。
【解决方案2】:

这可能是在 scanf 期间 str 溢出到 run 的堆栈缓冲区溢出。注释掉 scanf 以验证这一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-17
    • 2015-12-02
    • 1970-01-01
    • 1970-01-01
    • 2015-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多