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

C语言输入用户名密码触发Run-Time Check Failure #2栈损坏异常求助

解决栈溢出引发的Run-Time Check Failure #2异常

问题背景

编写了读取用户名和密码的代码,要求输入长度不超过最大值,超出则重新提示。但进入循环后,程序执行到return 0时抛出异常:Run-Time Check Failure #2 - Stack around the variable 'username_input' was corrupted. 尝试过scanf_s和fgets仍未解决。

原代码如下:

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

#define MAXNAME 30

int main() {
    char username_input[MAXNAME];
    char password_input[MAXNAME];

    username_input[MAXNAME - 1] = '\0';
    password_input[MAXNAME - 1] = '\0';

    printf("Please enter your username: ");
    while (scanf("%s", username_input) != 1 || strlen(username_input) > MAXNAME) {
        printf("Improper input.\nPlease enter your username: ");
    }

    printf("Please enter your password: ");
    while (scanf("%s", password_input) != 1 || strlen(password_input) > MAXNAME) {
        printf("Improper input.\nPlease enter your password: ");
    }
    return 0;
}

问题分析

  • 无限制的scanf("%s")导致栈溢出:当输入字符串长度超过MAXNAME-1(即29)时,scanf会直接向数组写入超出其容量的数据,覆盖栈上的其他内存区域,破坏栈结构,最终触发栈损坏检测异常。
  • 错误的长度判断条件:数组username_input的大小是MAXNAME(30),最多只能存储29个有效字符+1个终止符\0,原判断条件strlen(username_input) > MAXNAME不符合数组实际存储能力。
  • 输入缓冲区残留问题:输入超长时,超出部分会留在输入缓冲区中,后续scanf会直接读取这些残留数据,导致循环逻辑混乱。

解决方案

修改代码,限制scanf读取长度,修正判断条件,并处理输入缓冲区残留数据:

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

#define MAXNAME 30
#define MAX_INPUT_LEN (MAXNAME - 1)

int main() {
    char username_input[MAXNAME];
    char password_input[MAXNAME];
    int ret;
    int c;

    printf("Please enter your username: ");
    while (1) {
        // 限制读取字符数为MAX_INPUT_LEN,避免溢出
        ret = scanf("%29s", username_input);
        if (ret != 1 || strlen(username_input) > MAX_INPUT_LEN) {
            printf("Improper input.\nPlease enter your username: ");
            // 清空输入缓冲区残留数据
            while ((c = getchar()) != '\n' && c != EOF);
            continue;
        }
        break;
    }

    printf("Please enter your password: ");
    while (1) {
        ret = scanf("%29s", password_input);
        if (ret != 1 || strlen(password_input) > MAX_INPUT_LEN) {
            printf("Improper input.\nPlease enter your password: ");
            while ((c = getchar()) != '\n' && c != EOF);
            continue;
        }
        break;
    }

    return 0;
}

关键修改说明

  • 限制scanf读取长度:使用%29s格式,确保最多读取29个字符,数组末尾自动添加\0,不会超出数组容量。
  • 修正长度判断逻辑:检查长度是否超过MAX_INPUT_LEN(即29),匹配数组实际存储能力。
  • 清空输入缓冲区:输入无效时,用getchar()循环读取缓冲区残留字符直到换行或EOF,避免后续读取错误数据。

若偏好使用fgets,可按以下方式实现(需处理读取到的换行符):

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>

#define MAXNAME 30
#define MAX_INPUT_LEN (MAXNAME - 1)

int main() {
    char username_input[MAXNAME];
    char password_input[MAXNAME];
    char *newline;

    printf("Please enter your username: ");
    while (1) {
        if (fgets(username_input, MAXNAME, stdin) == NULL) {
            printf("Input error.\nPlease enter your username: ");
            continue;
        }
        // 去除fgets读取到的换行符
        newline = strchr(username_input, '\n');
        if (newline != NULL) {
            *newline = '\0';
        } else {
            // 输入超长时清空缓冲区
            int c;
            while ((c = getchar()) != '\n' && c != EOF);
        }
        if (strlen(username_input) > MAX_INPUT_LEN) {
            printf("Improper input.\nPlease enter your username: ");
            continue;
        }
        break;
    }

    printf("Please enter your password: ");
    while (1) {
        if (fgets(password_input, MAXNAME, stdin) == NULL) {
            printf("Input error.\nPlease enter your password: ");
            continue;
        }
        newline = strchr(password_input, '\n');
        if (newline != NULL) {
            *newline = '\0';
        } else {
            int c;
            while ((c = getchar()) != '\n' && c != EOF);
        }
        if (strlen(password_input) > MAX_INPUT_LEN) {
            printf("Improper input.\nPlease enter your password: ");
            continue;
        }
        break;
    }

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 00:32:06