You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

不同GCC版本输出异常:count变量无法正常累加的排查与修复

GCC版本差异导致DNS缓存代码count变量重置问题的分析与修复

问题重现

你遇到的这个版本差异问题很典型:同样的代码在GCC 5.4.1上运行完全正常,但在GCC 9.3环境中,每次循环都会把count变量意外重置为0。先回顾一下你提供的异常运行输出:

count:0
DNS cache empty.
Do you want to add/modify the DNS table(y/n)?y
Domain name: yahoo.com
IP address: 10.2.45.67

SERVER NAME	 IP ADDRESS
  yahoo.com          10.2.45.67

Do you want to add/modify the DNS table?(y/n)y
count:0
DNS cache empty.
Do you want to add/modify the DNS table(y/n)?n

根本原因:栈内存越界覆盖

问题的核心出在你读取用户选择的scanf调用上:

scanf("%s", &choice);

choice是一个单个char类型变量,但你误用了%s格式符——这个格式符是用来读取字符串的,它会把用户输入的字符(包括回车后的换行符)持续写入到&choice指向的内存地址,直到遇到空白字符,并且会自动在末尾添加\0作为字符串结束符。

因为choice只占用1字节的栈空间,多出来的\0就会溢出到相邻的栈内存区域。刚好在GCC 9.3的栈布局中,count变量的内存位置紧挨着choice的后面,所以每次执行这个scanf,count就被意外覆盖成0了。

而GCC 5.4.1的栈布局可能把count放在了离choice更远的位置,或者栈对齐规则不同,刚好没触发这个覆盖问题,但这只是巧合——你的代码本身存在严重的内存越界bug,在任何环境下都可能引发未知问题。

修复方案

把所有读取choice的scanf调用改成读取单个字符的格式,同时处理输入流中残留的空白字符(比如之前输入域名/IP后留下的换行):

// 替换原来的scanf("%s", &choice);
scanf(" %c", &choice);

这里的两个关键调整:

  • %c是专门读取单个字符的格式符,不会写入额外的\0,彻底避免内存越界
  • 前面的空格" %c"会自动跳过输入流中的所有空白字符(空格、换行、制表符等),避免读取到之前输入操作留下的无效换行符

另外,你的代码还有一个小逻辑bug:当修改已有域名的IP时,原来的代码会执行count +=1,这会导致count错误累加(实际条目数没增加,但计数器变大),所以需要在修改分支里抵消这个累加:

修改后的核心代码片段:

int main(int argc, char **argv){
    int count = 0;
    char choice;
    char domain_name[50];
    char ip_address[50];
    int i;
    do {
        printf("count:%d\n",count);
        if(count == 0) {
            printf("DNS cache empty.\n");
            printf("Do you want to add/modify the DNS table(y/n)?");
            scanf(" %c", &choice); // 修复读取choice的方式
            if(choice == 'n') {
                break;
            }
        }
        printf("Domain name: ");
        scanf("%s",domain_name);
        for(i=0; i<20; i++) {
            if(strcmp(domain_name,table[i].server_name) == 0 ){
                break;
            }
        }
    ip:
        strcpy(ip_address, " ");
        printf("IP address: ");
        scanf("%s", ip_address);
        if(validate_ip(ip_address) == 0){
            goto ip;
        }
        if(i == 20){
            strcpy(table[count].server_name,domain_name);
            strcpy(table[count].ip,ip_address);
        } else {
            strcpy(table[i].ip,ip_address);
            count -= 1; // 抵消后续的count+=1,避免计数器错误增加
        }
        count+=1;
        printDnsTable(count);
        choice = ' ';
        printf("\nDo you want to add/modify the DNS table?(y/n)");
        scanf(" %c", &choice); // 修复读取choice的方式
    } while(choice == 'y');
}

这样修改后,代码彻底解决了内存越界问题,同时修正了计数器的逻辑错误,在GCC 9.3以及其他任何GCC版本上都能稳定运行。

内容的提问来源于stack exchange,提问作者Mia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 13:17:50