如何避免C语言中的Stack Smashing Detected?代码问题排查求助
解决Luhn算法C程序中的“Stack Smashing Detected”错误
“Stack Smashing Detected”是因为代码数组越界访问破坏了栈内存结构,触发了GCC的栈保护机制。下面是具体问题分析和修复方案:
问题根源
数组arr越界
你定义了int arr[8],合法下标范围是0到7,但x初始值设为1,循环8次后x会递增到8,最后一次赋值arr[8] = d会访问数组边界外的内存,直接破坏栈上的其他数据,触发栈溢出检测。pow函数的精度问题
用pow(y,z)计算10的幂会返回double类型,浮点数的精度误差可能导致计算出的除数不准确,比如pow(10,15)可能不是精确的1000000000000000,进而导致提取的数字出错。数据类型溢出
long类型在32位系统中最大值是2147483647,而16位信用卡号(比如4111111111111111)已经超过这个范围,card变量会溢出,导致输入的卡号被截断。
修复方案
1. 修复数组越界
把x的初始值改为0,确保数组下标始终在0-7范围内:
int x = 0; // 从0开始 for(int i = 0; i < 8; i++) { // ... 其他代码 arr[x] = d; x++; }
2. 用整数运算替代pow
用一个整数变量保存当前除数,避免浮点精度问题:
unsigned long long divisor = 1000000000000000ULL; // 10^15 for(int i = 0; i < 8; i++) { long long digit_part = card / divisor; int d = digit_part % 10; // 直接取最后一位 arr[x] = d; x++; divisor /= 100; // 每次除以100,跳到下一个隔位数字 }
3. 更换合适的数据类型
把card改为unsigned long long,对应scanf格式符%llu:
unsigned long long card; do { printf("Enter the card number: "); scanf("%llu", &card); } while (card < 1000000000000000ULL); // 用ULL后缀确保是无符号长整型常量
4. 完善Luhn算法逻辑
当前代码只计算了乘2后的数字和,还需要加上未被乘2的数字的和,且乘2后若为两位数,需拆成个位+十位再求和,最后判断总和是否模10为0:
// 计算未乘2的数字之和 int sum_other = 0; unsigned long long temp_card = card; for(int i = 0; i < 8; i++) { sum_other += temp_card % 10; temp_card /= 100; } // 计算乘2后的数字之和(拆分两位数) int sum_double = 0; for(int j = 0; j < 8; j++) { int doubled = arr[j] * 2; sum_double += (doubled / 10) + (doubled % 10); } int total_sum = sum_other + sum_double; if (total_sum % 10 == 0) { printf("This checks out, boss.\n"); } else { printf("Security will escort you out of the building big man.\n"); }
完整修复后的代码
#include <stdio.h> int main(void) { unsigned long long card; do { printf("Enter the card number: "); scanf("%llu", &card); } while (card < 1000000000000000ULL); int arr[8]; int x = 0; unsigned long long divisor = 1000000000000000ULL; for(int i = 0; i < 8; i++) { long long digit_part = card / divisor; int d = digit_part % 10; arr[x] = d; x++; divisor /= 100; } // 计算未乘2的数字之和 int sum_other = 0; unsigned long long temp_card = card; for(int i = 0; i < 8; i++) { sum_other += temp_card % 10; temp_card /= 100; } // 计算乘2后的数字之和(拆分两位数) int sum_double = 0; for(int j = 0; j < 8; j++) { int doubled = arr[j] * 2; sum_double += (doubled / 10) + (doubled % 10); } int total_sum = sum_other + sum_double; if (total_sum % 10 == 0) { printf("This checks out, boss.\n"); } else { printf("Security will escort you out of the building big man.\n"); } return 0; }
内容的提问来源于stack exchange,提问作者Vihaan Kaustuv
相关产品推荐
相关产品推荐

