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

C语言实现getIntPositive正整数校验时nullptr错误排查

问题描述

练习函数与指针相关编程时,耗时超过12小时调试代码仍未解决nullptr相关报错,检索公开的nullptr问题解决方案均未修复问题。
本次任务要求实现int getIntPositive(int *xPtr)函数,功能如下:

  • 读取用户输入的数值(任务默认测试输入为-1、0、24)
  • 校验输入是否为非零正整数
  • 校验通过的数值返回的同时,赋值给指针形参指向的内存空间
  • 最终将值传递给预置的int testIntFunction(void)测试函数
    题目要求main.c中的主函数、测试函数及其余预置代码均不可修改,仅可编写getIntPositive函数的实现逻辑,以下代码已删除main.c中与该问题无关的其余内容。
    当前需要全部通过3项内置测试,但代码存在两类互斥异常:
  • 第一类:仅能通过Test1,执行Test2时触发nullptr错误
  • 第二类:调整代码顺序后可通过Test2,但Test1、Test3失败,失败原因为要求intA与intB值相等,但实际运行时intA为0、intB为24,二者不相等
相关代码
// ---------------------------------------
// Macros and headers
// ---------------------------------------
#define MAX_PROD 3
#define TEST_NEG    -1
#define TEST_ZERO   0
#define TEST_INT    24
#define TEST_DBL    82.5
#include <stdio.h>

// ---------------------------------------
// Function prototypes
// ---------------------------------------
int testIntFunction(void);
int getIntPositive(int *xPtr);

// ---------------------------------------
// Main entry-point to the program (main.c) Must not modify, fixed
// ---------------------------------------
int main(void)
{
    int preTestFailed = 0;

    printf("============================\n");
    printf("Pre-testing Helper Functions\n");
    printf("============================\n\n");
    
    preTestFailed += testIntFunction();

    if (preTestFailed)
    {
        printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n");
        printf("  Pretesting revealed ERRORS in the helper functions.\n");
        printf("  Review where the tests failed and fix these errors\n");
        printf("  before continuing.\n");
        printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n\n");
    }
    else
    {
        printf("===========================\n");
        printf("Starting Main Program Logic\n");
        printf("===========================\n\n");

        // Entry-point to program logic
        start();
    }

    return 0;
}
// ---------------------------------------
// My own function (placed in another .c file) The only part can be modified.
// ---------------------------------------

// 1. Get user input of int type and validate for a positive non-zero number
//    (return the number while also assigning it to the pointer argument)
int getIntPositive(int *xPtr)
{
    int x;
    int flag = 0;
    do {
        scanf("%d", &x);
        if (x <= 0)
        {
            printf("ERROR: Enter a positive value: ");
            flag = 1;
        }
        else
        {
            flag = 0;
            *xPtr = x;
            xPtr = &x;
        }
    } while (flag != 0);
    return *xPtr;
}
// ---------------------------------------
// Preset functions ( Must not modify, fixed)
// ---------------------------------------
int testIntFunction(void)
{
    int intA = 0, intB = 0, fail=0;

    printf("------------------------\n");
    printf("Function: getIntPositive\n");
    printf("------------------------\n");
    printf("For each of these tests, enter the following\n");
    printf("three values (space delimited):  %d %d %d\n\n", TEST_NEG, TEST_ZERO, TEST_INT);

    //-----------------------------------
    // Test-1: argument and return value
    printf("TEST-1: ");
    intB = getIntPositive(&intA);
    if (intA == intB && intA == TEST_INT)
    {
        printf("<PASSED>\n");
    }
    else
    {
        printf("<!!! FAILED !!!>\n");
        fail++;
    }

    //-----------------------------------
    // Test-2: return value only
    intA = intB = 0;
    printf("TEST-2: ");
    intA = getIntPositive(NULL);
    if (intA == TEST_INT)
    {
        printf("<PASSED>\n");
    }
    else
    {
        printf("<!!! FAILED !!!>\n");
        fail++;
    }

    //-----------------------------------
    // Test-3: argument only
    intA = intB = 0;
    printf("TEST-3: ");
    getIntPositive(&intA);
    if (intA == TEST_INT)
    {
        printf("<PASSED>\n\n");
    }
    else
    {
        printf("<!!! FAILED !!!>\n");
        fail++;
    }

    return fail;
}
void start() {}
异常表现

第一版代码异常

第一版代码运行时,执行到Test2程序因nullptr错误终止,调试查看局部变量可见x=24,xPtr=0x00000000空指针,运行输出如下:

============================
Pre-testing Helper Functions
============================

------------------------
Function: getIntPositive
------------------------
For each of these tests, enter the following
three values (space delimited):  -1 0 24

TEST-1: -1 0 24
ERROR: Enter a positive value: ERROR: Enter a positive value: <PASSED>
TEST-2: -1 0 24
ERROR: Enter a positive value: ERROR: Enter a positive value:

调整代码顺序后的异常

将else分支内代码顺序调整为先执行xPtr = &x、再执行*xPtr = x,nullptr错误消失,但Test1、Test3运行失败,调试可见intA=0、intB=24,不符合预期,运行输出如下:

============================
Pre-testing Helper Functions
============================

------------------------
Function: getIntPositive
------------------------
For each of these tests, enter the following
three values (space delimited):  -1 0 24

TEST-1: -1 0 24
ERROR: Enter a positive value: ERROR: Enter a positive value: <!!! FAILED !!!>
TEST-2: -1 0 24
ERROR: Enter a positive value: ERROR: Enter a positive value: <PASSED>
TEST-3: -1 0 24
ERROR: Enter a positive value: ERROR: Enter a positive value: <!!! FAILED !!!>
错误原因

代码存在两个核心逻辑错误:

  1. 未做空指针校验:Test2直接传入NULL作为参数,原代码不判断指针是否有效直接解引用执行*xPtr = x,必然触发空指针访问崩溃。
  2. 错误修改形参指针的指向:原代码在else分支中执行xPtr = &x,把形参指针指向了函数内的局部变量x,当外部传入有效地址(比如&intA)时,赋值操作只会修改局部变量x,不会写入外部传入的地址对应的内存,导致Test1、Test3中的intA始终是初始值0,校验失败。
修复方案

修改getIntPositive函数逻辑,增加空指针判断,不修改形参指针的指向,直接返回校验通过的局部变量值即可,正确实现如下:

int getIntPositive(int *xPtr)
{
    int x;
    int flag = 0;
    do {
        scanf("%d", &x);
        if (x <= 0)
        {
            printf("ERROR: Enter a positive value: ");
            flag = 1;
        }
        else
        {
            flag = 0;
            // 仅当传入指针非空时,才给指针指向的内存空间赋值
            if (xPtr != NULL)
            {
                *xPtr = x;
            }
        }
    } while (flag != 0);
    // 直接返回校验通过的输入值,无需解引用指针
    return x;
}

修复后三个测试场景全部适配:

  • Test1:传入&intA,指针有效,intA被赋值为24,返回值24赋值给intB,二者相等,校验通过
  • Test2:传入NULL,跳过指针赋值逻辑,直接返回24,intA接收到返回值24,校验通过
  • Test3:传入&intA,指针有效,intA被赋值为24,无需使用返回值,校验通过

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 17:45:35