C语言函数使用双指针返回数组最值地址时程序无输出问题排查
问题描述
- 运行环境:Mac系统下使用VSCode编写、运行C语言代码
- 预期功能:声明长度为5的int数组,以及两个一级指针
maxPtr、minPtr;定义形参为两个int二级指针的MaxAndMin函数,在函数内遍历数组,让maxPtr存储数组最大值的地址,minPtr存储数组最小值的地址,最终输出最大值、最小值与测试字符串"Hi" - 异常表现:完成5个整数的输入流程后程序直接终止,后续
printf("%d",*maxPtr)、printf("%d",*minPtr)、printf("Hi")均未执行。
原始问题代码:
#include <stdio.h> void MaxAndMin(int* str,int** max, int** min) { int i; int maxnum=0,minnum=0; for(i=0; i<5; i++) { if(maxnum< str[i]) { maxnum =str[i]; *max = &str[i]; } if(minnum > str[i]) { minnum = str[i]; *min = &str[i]; } } } int main(void) { int i,len; int* maxPtr; int* minPtr; int arr[5]={}; for(i=0; i<5; i++) { printf("%d번째 정수입력 입니다.",i+1); scanf("%d", &arr[i]); } MaxAndMin(arr,&maxPtr,&minPtr); printf("%d",*maxPtr); printf("%d",*minPtr); printf("Hi"); return 0; }
实际运行输出:
> Executing task: ./test < 1번째 정수입력 입니다.1 2번째 정수입력 입니다.2 3번째 정수입력 입니다.3 4번째 정수입력 입니다.4 5번째 정수입력 입니다.5 Terminal will be reused by tasks, press any key to close it.
异常根本原因
程序崩溃的核心原因是野指针访问触发段错误,同时代码存在最值比较的逻辑漏洞:
- 野指针问题:
MaxAndMin函数中用于比较的临时变量maxnum、minnum被初始化为0,当测试输入为1、2、3、4、5这类全大于0的数值时,minnum > str[i]的判断条件永远不成立,始终不会执行*min = &str[i]的赋值操作。main函数中的minPtr是未初始化的局部变量,存储的是随机的非法内存地址,后续执行printf("%d",*minPtr)时尝试访问无权限的内存地址,会被操作系统直接发送段错误信号强制终止,后续所有代码都不会执行。
同理如果测试输入全为负数,maxnum < str[i]的判断永远不成立,maxPtr也会成为野指针触发崩溃。 - 逻辑漏洞:即使不触发野指针,将最值初始值固定设为0的写法也是错误的:全正数数组无法正确得到最小值,全负数数组无法正确得到最大值,计算结果不符合预期。
修复方法
- 进入
MaxAndMin函数后,先将maxnum、minnum初始化为数组第一个元素的值,同时给*max、*min赋值为第一个元素的地址,从根源避免野指针 - 数组遍历从下标1开始,逐个比较更新最值和对应指针即可
- 输出语句末尾增加换行符,避免行缓冲导致的输出不及时问题
修复后可正常运行的代码:
#include <stdio.h> void MaxAndMin(int* str,int** max, int** min) { int i; // 用数组第一个元素初始化最值和对应指针 int maxnum = str[0], minnum = str[0]; *max = &str[0]; *min = &str[0]; // 从第二个元素开始遍历比较 for(i = 1; i < 5; i++) { if(maxnum < str[i]) { maxnum = str[i]; *max = &str[i]; } if(minnum > str[i]) { minnum = str[i]; *min = &str[i]; } } } int main(void) { int i; int* maxPtr; int* minPtr; int arr[5]; for(i = 0; i < 5; i++) { printf("%d번째 정수입력 입니다.", i+1); scanf("%d", &arr[i]); } MaxAndMin(arr, &maxPtr, &minPtr); printf("max: %d\n", *maxPtr); printf("min: %d\n", *minPtr); printf("Hi\n"); return 0; }
内容的提问来源于stack exchange,提问作者chobodark
相关产品推荐
相关产品推荐

