为何我的C++代码出现SIGSEGV运行时错误?求排查帮助
排查CodeChef题目CHPINTU中的SIGSEGV运行时错误
我看到你在解决这道题时碰到了SIGSEGV运行时错误,咱们一步步拆解问题根源,再给出修正方案:
问题1:非标准变长数组引发栈溢出
C++标准并不支持int f[n]、int freq[m+1]这类变长数组(VLA)——虽然部分编译器(比如GCC)会提供扩展支持,但栈空间本身非常有限,如果输入的n或m数值较大,直接在栈上分配这类数组很容易触发栈溢出,这就是SIGSEGV错误的核心原因之一。
问题2:隐藏的逻辑错误(间接引发风险)
你把freq数组用memset初始化为-1,然后直接执行freq[f[i]] += p[i]——如果某个食物类型是第一次出现,freq[f[i]]的初始值是-1,累加后会变成p[i]-1,这完全不符合“统计该类型食物总价格”的需求,虽然这不会直接导致SIGSEGV,但会让你的答案完全错误。
问题3:潜在的数组越界风险
如果输入的f[i]值超出了1~m的范围(比如等于0或者大于m),freq[f[i]]就会访问数组边界外的内存,这也会直接触发SIGSEGV。虽然题目可能保证输入合法,但代码里没有边界检查,存在隐患。
修正后的代码示例
#include <iostream> #include <vector> #include <climits> using namespace std; int main() { int t; cin >> t; while(t != 0) { int n, m; cin >> n >> m; // 用vector替代变长数组,内存分配在堆上,避免栈溢出 vector<int> f(n), p(n); for(int i = 0; i < n; i++) cin >> f[i]; for(int i = 0; i < n; i++) cin >> p[i]; // 直接用vector构造函数初始化,替代memset,更直观安全 vector<int> freq(m + 1, 0); vector<bool> avail(m + 1, false); for(int i = 0; i < n; i++){ // 加边界检查,避免越界访问 if(f[i] >= 1 && f[i] <= m) { freq[f[i]] += p[i]; avail[f[i]] = true; } } int min_val = INT_MAX; // 从1开始遍历,因为食物类型是1~m,无需遍历0 for(int i = 1; i <= m; i++){ if(avail[i] && freq[i] < min_val){ min_val = freq[i]; } } cout << min_val << "\n"; t--; } return 0; }
关键修正点说明
- 用
vector替代变长数组:内存分配在堆上,避免栈溢出问题,同时符合C++标准。 - 调整
freq初始化逻辑:直接初始化为0,第一次累加时就能得到正确的总价格。 - 增加边界检查:确保
f[i]在合法范围内,避免越界访问。 - 优化遍历范围:从1开始遍历
freq,因为食物类型编号是1到m,无需处理索引0。
内容的提问来源于stack exchange,提问作者Saurabh Dubey
相关产品推荐
相关产品推荐

