动态数组添加长整数时出现内存分配错误,求问题排查
问题分析与修复
你的代码核心问题是数组越界操作破坏了堆内存结构,同时还有其他内存管理和逻辑错误,以下是具体问题和修复方案:
主要错误点
1. 数组越界读写,直接破坏堆
找到因数时的内存复制逻辑完全错误:
- 当你创建长度为
++dnum的temp数组后,执行memcpy(temp, divisors, dnum * sizeof(long)),但此时旧的divisors数组长度是dnum-1(上一次的因数个数),你读取了超出旧数组范围的内存。 - 更严重的是
memcpy(temp + dnum, added_array, sizeof(long)):temp数组的有效索引是0到dnum-1,temp + dnum已经超出数组边界,越界写入会直接破坏堆的元数据,触发free()错误或断言失败。
2. 多余的内存分配与泄漏
added_array是完全不必要的临时数组,而且你注释了它的释放代码,导致每次找到因数都会泄漏4/8字节的内存。
3. 越界访问数组末尾
printf("Final number = %ld\n", divisors[num-1]);中,divisors数组的实际长度是因数个数dnum,而num-1远大于dnum-1(比如num=100,因数个数只有9个),这会越界访问未知内存,导致程序崩溃或输出垃圾值。
4. 参数类型不匹配
main中输入的是long num,但function的参数是int num,如果输入数值超过int的范围(如大于2^31-1),会被截断,导致逻辑错误。
修复后的代码(手动内存管理版)
#include <cstdlib> #include <iostream> #include <cstring> int function(long num) { int dnum = 0; long* divisors = nullptr; for (long i = 1; i <= num; i++) { if (num % i == 0) { // 创建长度+1的新数组 long* temp = new long[dnum + 1]; // 复制旧数组的所有元素(仅当旧数组非空时) if (dnum > 0) { memcpy(temp, divisors, dnum * sizeof(long)); } // 添加新因数到数组末尾 temp[dnum] = i; // 释放旧数组 delete[] divisors; // 更新指针和计数 divisors = temp; dnum++; printf("dnum = %d\n", dnum); printf("new num = %ld\n", i); } } if (dnum > 0) { printf("Final number = %ld\n", divisors[dnum - 1]); delete[] divisors; } else { printf("No divisors found\n"); } return dnum; } int main() { long num; std::cin >> num; int result = function(num); printf("%d\n", result); return 0; }
更简洁安全的版本(使用std::vector)
C++中推荐用std::vector自动管理内存,完全避免手动分配释放的错误:
#include <iostream> #include <vector> int function(long num) { std::vector<long> divisors; for (long i = 1; i <= num; i++) { if (num % i == 0) { divisors.push_back(i); printf("dnum = %zu\n", divisors.size()); printf("new num = %ld\n", i); } } if (!divisors.empty()) { printf("Final number = %ld\n", divisors.back()); } else { printf("No divisors found\n"); } return divisors.size(); } int main() { long num; std::cin >> num; int result = function(num); printf("%d\n", result); return 0; }
内容的提问来源于stack exchange,提问作者Damon Crowley
相关产品推荐
相关产品推荐

