单个IP差值测试正常,连续执行两测试时程序触发SIGABRT崩溃求助
问题根源:数组越界写入破坏栈结构
你的程序崩溃的核心问题是ip2array函数存在数组越界写入,破坏了栈上的函数返回地址或其他关键数据,导致第二次调用函数时栈结构彻底损坏,触发SIGABRT信号。
具体问题分析
- 无边界的数组写入:
ip_int是长度为4的uint8_t数组,但ip2array里的i没有限制最大值。当解析完IP的4个段后,循环仍可能继续执行,导致i超过3,写入ip_int[4]及以后的内存(栈上的其他区域)。 - 指针越界访问:每次调用
strtoul后直接执行p++,当处理到IP最后一个段时,p会指向字符串结束符'\0',此时p++会让指针指向字符串外的未知内存,循环条件*p != '\0'可能依然成立,导致后续解析操作完全越界。
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <inttypes.h> // 安全的IP转数组函数 void ip2array(const char* ip_str, uint8_t* ip_int) { int i = 0; const char* p = ip_str; while (*p != '\0' && i < 4) { // 限制i不超过3,避免数组越界 ip_int[i++] = (uint8_t)strtoul(p, (char**)&p, 10); // 只有当前是分隔符'.'时才移动指针,避免越界 if (*p == '.') { p++; } } } uint32_t ips_between(const char* start, const char* end) { uint8_t ip_start[4] = {0}; uint8_t ip_end[4] = {0}; ip2array(start, ip_start); ip2array(end, ip_end); // 用移位代替pow,避免浮点计算误差和性能问题 uint32_t start_ip = ((uint32_t)ip_start[0] << 24) | ((uint32_t)ip_start[1] << 16) | ((uint32_t)ip_start[2] << 8) | ip_start[3]; uint32_t end_ip = ((uint32_t)ip_end[0] << 24) | ((uint32_t)ip_end[1] << 16) | ((uint32_t)ip_end[2] << 8) | ip_end[3]; return end_ip - start_ip; } int main() { printf("%u\n", ips_between("10.0.0.0", "10.0.0.50")); // test A printf("%u\n", ips_between("20.0.0.10", "20.0.1.0")); // test B return 0; }
额外优化点
- 替换pow为位运算:原代码用
pow(2, i*8)进行计算,会引入浮点运算的精度误差和性能损耗,直接用移位操作<<更高效且准确。 - 拆分数组存储:将
ip[2][4]拆分为ip_start和ip_end,代码可读性更好。 - 可选:用系统函数简化解析:如果系统支持
arpa/inet.h,可以直接用inet_addr函数将IP字符串转为uint32_t,彻底避免手动解析的错误:
#include <arpa/inet.h> uint32_t ips_between(const char* start, const char* end) { uint32_t start_ip = ntohl(inet_addr(start)); uint32_t end_ip = ntohl(inet_addr(end)); return end_ip - start_ip; }
内容的提问来源于stack exchange,提问作者VioletLovesJasmine
相关产品推荐
相关产品推荐

