C语言二进制操作程序出现stack smashing detected错误的排查咨询
问题:程序运行结束触发"stack smashing detected"错误
错误含义
stack smashing detected是GCC编译器栈保护机制的报错,说明程序越界写入了栈内存,破坏了栈的结构,系统为防止内存泄露或程序崩溃,强制终止了进程。
代码中的问题分析
代码多处存在数组越界写入的情况,这是触发错误的核心原因:
- 栈数组大小不足:
get_nbits、replace_nbits等函数里定义的int bin_num[9];数组仅能存储9位二进制,但当输入num的二进制位数(cnt)加上填充0的循环次数时,下标会超过数组最大索引(8),导致越界写入栈内存。 - 填充0逻辑错误:以
get_nbits为例,for(int i=0;i<8;i++)循环中bin_num[i+cnt] = 0;,当cnt为8时,i+cnt最大为15,远超数组的9个元素范围,直接破坏栈结构。 - 堆内存越界:
print_bits函数中,当n > cnt时,for(int i=0;i<n;i++)循环写入bin_num[i+cnt],会超过malloc(n*sizeof(int))分配的内存范围,越界写入堆内存。
解决办法
1. 扩大栈数组的大小
将栈上存储二进制的数组从[9]改为[32](C语言中int通常为32位,足够存储所有int类型的二进制位),避免因位数过多导致越界。
2. 修复填充0的逻辑
把固定循环8次填充0的代码,改为填充到数组的有效范围。比如在get_nbits中:
// 原错误代码 // for(int i=0;i<8;i++) // { // bin_num[i+cnt] = 0; // } // 修改后 for(int i=cnt; i<32; i++) { bin_num[i] = 0; }
3. 修复print_bits的堆内存越界
调整填充0的循环,确保只写入malloc分配的内存范围内:
// 原错误代码 // if(n>num) // { // for(int i=0;i<n;i++) // { // bin_num[i+cnt] = 0; // } // } // 修改后 for(int i=cnt; i<n; i++) { bin_num[i] = 0; }
同时增加malloc失败的检查,避免空指针访问:
int* bin_num = malloc(n*sizeof(int)); if(!bin_num) { printf("Memory allocation failed\n"); return; }
4. 增加输入合法性检查
对用户输入的n、pos等参数做边界校验,比如pos不能超过31(int的最高位索引),n不能大于32,防止因非法输入导致的越界访问。
修改后的示例代码片段
以get_nbits为例:
void get_nbits(int num, int n) { int bin_num[32]; // 扩大为32位数组 int cnt = 0; int bin_dig = 0; int multiple = 1; int decimal_num = 0, base = 1, rem; while (num > 0) { bin_num[cnt] = num % 2; num = num / 2; cnt++; } // 填充0到32位,不越界 for(int i=cnt; i<32; i++) { bin_num[i] = 0; } printf("The binary form of given number: "); for(int i=7;i>=0;i--) { printf("%d ",bin_num[i]); } for(int i=0;i<n;i++) { bin_dig = bin_dig + multiple*bin_num[i]; multiple*=10; } while ( bin_dig > 0) { rem = bin_dig % 10; decimal_num = decimal_num + rem * base; bin_dig = bin_dig / 10; base = base * 2; } printf("\nThe decimal number is: %d\n",decimal_num); }
内容的提问来源于stack exchange,提问作者Balaji Baski
相关产品推荐
相关产品推荐

