意外行为,字符串后打印垃圾

时间:2015-06-26 11:17:48

标签: c gcc

我只是在终止应用程序之前尝试动画一些字符串。我打电话给附上的一段代码。但它一直在打印垃圾直到核心倾倒。

这是代码..

int terminate_msg(int quit_flag)
{
    char server_msg[] = "\nApplication Not Alive";
    char exit_msg[] = "\nTerminating Application...\n";
    char *ch;
    int i = 0;

    if(quit_flag == 1) {
        printf("%s%s", server_msg, exit_msg);
        while((ch = server_msg + i) != NULL) {
            printf("%c",*ch);
            fflush(stdout);
            usleep(100000);
            i++;
        }
        i = 0;
        sleep(2);
        while((ch = exit_msg + i) != NULL) {
            printf("%c",*ch);
            fflush(stdout);
            usleep(100000);
            i++;
        }
        sleep(2);
    }   
    return 0;
}

输出:

Application Not Alive
Terminating Application...

Application Not Alive
Terminating Application...
���І�JS�dX��lX���p�dX��X��$���P
l�UZ��D~�]P�up��IS�@q�P�q�M�dX��І@��!p�\X��^C

虽然第一次printf()打印正确,但不知道为什么垃圾打印最后会出现。如果有任何问题,垃圾应该在第一次循环后也会出现。

请注意,在比较*ch != '\0'时,一切正常。

这段代码有什么问题?我在linux环境中使用gcc

2 个答案:

答案 0 :(得分:5)

这个条件错了

while((ch = server_msg + i) != NULL)

你应该试试这个

char ch;

while ((ch = server_msg[i]) != '\0')
    printf("%c", ch);

条件是测试指针是否为NULL,这很可能不会发生,你必须测试的是,如果到达了'\0'终止字节,那么你需要取消引用指针。

由于NULL在c中基本上是(void *) 0,如果server_msg是有效指针,它的值肯定是> 0,那么{{1}的值仅通过递增指针无法访问1}},因此循环永远不会结束,并且程序在传递指向的有效内存后继续访问指针。

当然,这里也会出现同样的问题

(void *) 0

答案 1 :(得分:3)

在您的情况下,在循环内部,其增量值为ii++;

 server_msg + i

指向每次迭代中server_msg的下一个内存位置。这里的问题是,无法保证立即的下一个地址(字符串终止后)将是NULL。它很可能是有效的内存区域(最有可能是这样)通过NULL检查。

因此,你的循环不会中断(如你所料),它将继续执行并(尝试)访问越界内存区域,然后调用undefined behaviour。因此,输出和行为也是未定义的。

相反,您应该将*ch值作为\0回复,以判断字符串终止。