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

Access violation写入位置错误:C语言输入函数异常排查

问题分析与修复

核心错误原因

  1. 非法赋值触发内存访问违规
    代码中*cstringValue = strlist;是致命错误:cstringValue是指向目标字符数组的指针,*cstringValue仅代表数组的第一个字符(1字节),而strlist作为数组名会退化为指针(x64下占8字节),强行将指针值写入单个char的内存空间,直接越界导致内存访问违规。此外strlist是函数局部数组,函数返回后内存会被释放,即便赋值逻辑正确也会产生野指针。

  2. scanf_s使用错误
    scanf_s("%s", &strlist)存在两处问题:

    • strlist本身就是数组首元素地址,无需加&;
    • scanf_s处理字符串时必须指定缓冲区大小,否则存在缓冲区溢出风险。
  3. 冗余的长度计算
    手动循环计算字符串长度完全可以用标准库函数strlen替代,更简洁可靠。

  4. 输入缓冲区残留问题
    用户输入不符合要求时,输入缓冲区可能残留未处理的字符,导致后续scanf_s读取异常,陷入死循环。


修正后的代码

inputCString函数

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

void inputCString(char *cstringValue, int min, int max) {
    int strsize = 0;
    char strlist[50] = { '\0' };
    int c;

    // 清理函数调用前可能残留的换行符
    while ((c = getchar()) != '\n' && c != EOF);

    while (1) {
        // 正确使用scanf_s:传入数组首地址+缓冲区大小
        if (scanf_s("%s", strlist, (unsigned)_countof(strlist)) != 1) {
            // 输入错误时清理缓冲区
            while ((c = getchar()) != '\n' && c != EOF);
            printf("ERROR: Invalid input, please enter a string: ");
            continue;
        }

        strsize = strlen(strlist);
        if (strsize >= min && strsize <= max) {
            // 用安全的strcpy_s复制字符串到目标缓冲区,需指定目标缓冲区大小
            strcpy_s(cstringValue, max + 1, strlist);
            break;
        } else if (min == max) {
            printf("ERROR: String length must be exactly %d chars: ", min);
        } else {
            printf("ERROR: String length must be between %d and %d chars: ", min, max);
        }
        // 清理当前输入的残留字符,避免影响下一次读取
        while ((c = getchar()) != '\n' && c != EOF);
    }
}

测试函数(修正输入提示)

void test06_inputCString(void)
{
    char cstringValue[7] = { '\0' };

    printf("TEST #6: - Instructions:\n"
           "1) Enter the word 'horse'   [ENTER]\n"  // 长度5,不符合要求
           "2) Enter the word 'chicken' [ENTER]\n"  // 长度7,不符合要求
           "3) Enter the word 'Beaver'  [ENTER]\n"  // 长度6,符合要求
           ":>");

    inputCString(cstringValue, 6, 6);

    printf("////////////////////////////////////////\n");
    printf("TEST #6 RESULT: ");
    printf("%s (expected result: Beaver)\n", cstringValue);
    printf("////////////////////////////////////////\n\n");
}

关键修复说明

  • 用strcpy_s替代非法赋值:安全复制字符串到目标缓冲区,同时指定缓冲区大小(max+1是为了预留字符串结束符\0的位置);
  • 修正scanf_s参数:添加缓冲区大小,避免缓冲区溢出;
  • 增加输入缓冲区清理逻辑:防止错误输入导致的死循环;
  • 替换手动长度计算为strlen:简化代码同时提升可靠性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 08:02:02