竞赛编程代码出现Segmentation Fault,无法定位原因求排查
Hey,我帮你排查出代码触发Segmentation Fault的核心问题了,咱们一步步来看:
首先说最致命的问题:栈溢出,这是绝大多数情况下触发段错误的原因,另外还有个潜在的下标越界风险,咱们逐个分析:
1. 变长数组(VLA)的栈空间瓶颈
你用了long int a[size]和long int b[size2]这种变长数组——栈内存的大小是有限的(一般系统默认只有几MB,比如Linux是8MB)。举个实际的例子:如果size取1000,size2就是1000000,b数组要占1000000 * 8字节 = 8MB,刚好卡栈的上限;要是size到2000,size2变成4000000,b直接要32MB,远远超出栈的承载能力,直接触发栈溢出,也就是你看到的Segmentation Fault。
2. 隐藏的数组下标溢出风险
另外,i和j都是long int类型,计算i*size+j的时候,如果size太大,这个值可能会超出long int的范围(比如32位系统下long int最大是2^31-1),整数溢出后会变成非法的下标值,访问不属于你的内存区域,也可能触发段错误。
给你两个修复方案
方案一:用堆内存分配(强烈推荐)
堆内存的空间比栈大得多,用malloc在堆上分配数组就能解决栈溢出的问题,记得用完要释放内存避免泄漏:
#include<stdio.h> #include<stdlib.h> int main() { int t; scanf("%d",&t); while(t-->0) { long int size; scanf("%ld",&size); long int size2 = size * size; // 堆上分配数组 long int *a = malloc(size * sizeof(long int)); long int *b = malloc(size2 * sizeof(long int)); // 一定要检查分配是否成功,避免空指针 if(a == NULL || b == NULL) { printf("内存分配失败,请检查输入的size是否过大\n"); return 1; } long int i; for(i=0;i<size;i++) { scanf("%ld",&a[i]); } long int j; long int y = 2 * a[0]; for(i=0;i<size;i++) { for(j=0;j<size;j++) { if(i!=0 && j!=0) { b[i*size + j] = a[i] + a[j]; y ^= b[i*size + j]; } } } printf("%ld\n",y); // 释放堆内存 free(a); free(b); } return 0; }
方案二:限制size的最大值(仅适合小数据场景)
如果题目明确说size不会太大(比如不超过1000),可以用固定大小的数组,避免变长数组的栈溢出问题:
#include<stdio.h> #define MAX_ALLOWED_SIZE 1000 // 定义最大允许的size int main() { int t; scanf("%d",&t); while(t-->0) { long int size; scanf("%ld",&size); // 提前判断size是否超标 if(size > MAX_ALLOWED_SIZE) { printf("size超过最大限制\n"); continue; } long int size2 = size * size; long int a[MAX_ALLOWED_SIZE], b[MAX_ALLOWED_SIZE*MAX_ALLOWED_SIZE]; // 后续逻辑和原来一样 long int i; for(i=0;i<size;i++) { scanf("%ld",&a[i]); } long int j; long int y = 2 * a[0]; for(i=0;i<size;i++) { for(j=0;j<size;j++) { if(i!=0 && j!=0) { b[i*size + j] = a[i] + a[j]; y ^= b[i*size + j]; } } } printf("%ld\n",y); } return 0; }
顺带提个逻辑小问题(不触发段错误,但影响结果)
当size=1的时候,你的循环条件i!=0 && j!=0永远不满足,y会一直是2*a[0],如果题目里有size=1的测试用例,这个结果可能不符合题目要求,你可以根据题目描述调整这部分逻辑。
内容的提问来源于stack exchange,提问作者longnightofsolace

