起因是一个奇怪的问题:之前完整的程序(一组方程求解加两个基于agent的模型)已经经过调试可以运行,一直在用release模式运行。直到这次更新添加新功能,试着用debug调试发现算出了异常的数值,但release运行是正常的,可以计算出正确的结果。

Debug和Release的区别

Debug称为调试版本,包含调试信息,并且不作任何优化,方便调试。Release称为发布版本,通常进行了各种优化,不保存调试信息,使得程序在代码大小和速度上是最优的。

因此两者其实本质上是相同,只不过是两组编译选项的合集。两者最大的区别在于优化程度。

Debug正常但是Release出问题的原因可能有:

  • Debug模式以32字节为单位分配内存,例如当申请24字节内存时,Release模式下是正常的分配24字节,Debug模式会分配32字节,多了8字节,所以有些数组越界问题在Debug模式下可以安全运行,Release模式下就会出问题。
  • 数据溢出问题,在一个函数中,存在某些从未被使用的变量,且函数内存在数据溢出问题,在Debug模式下可能不会产生问题,因为不会对该变量进行优化,它在栈空间中还是占有几个字节,但是Release模式下可能会出问题,Release模式下可能会优化掉此变量,栈空间相应变小,数据溢出就会导致栈内存损坏
    参考:https://www.zhihu.com/question/443340911/answer/1720297063

Debug出错但Release正常的情况:

  • Debug模式有运行时检查,检测栈溢出。如果有数据越界,就会弹红叉框(run time check error)。Release模式没有,程序可以继续运行,但溢出可能导致程序在其他未知的情况下出错或崩溃。
  • 两种模式下所需要依赖的外部环境不同,导致Release模式正常而Debug模式下会崩溃

这次问题的原因是,通过new分配的一维数组没有初始化。在Debug模式下没有初始化为0,而在Release模式下全部初始化为0.

C++动态数组初始化

定义:

1
int *a = new int[5];

new表达式分配了一个包含5个int型元素的数组,并返回指向第一个元素的指针。

元素只能初始化为元素类型的默认值,而不能用初始化列表为数组元素提供不同的初值。对于内置数据类型元素的数组,必须用()执行初始化,否则程序不执行初始化操作。

1
2
int *a = new int[5];   // 没有初始化
int *b = new int[5](); // 每个元素初始化为0

类类型元素的数组,无论是否使用(),都会自动调用默认构造函数来初始化

1
2
string *sa = new string[10];   // 每个元素调用默认构造函数来初始化
string *sb = new string[10](); // 每个元素调用默认构造函数来初始化

注意使用结束后要释放

1
delete []a;