Eigen中对同一变量赋值矩阵切片触发未定义行为的咨询
Eigen中直接赋值矩阵切片给原变量触发未定义行为的原因与解决办法
你遇到的问题核心在于Eigen的表达式模板延迟求值机制,以及赋值操作中可能出现的内存重叠/失效问题:
为什么直接赋值会出问题?
Eigen为了性能优化,不会立即计算诸如my_mat(Eigen::all, sub_cols)这样的切片表达式,而是生成一个"表达式对象",直到赋值操作执行时才会真正去读取原矩阵的数据并计算结果。
但当你执行my_mat = 切片表达式时:
- 首先Eigen会检查切片后的矩阵尺寸和原矩阵是否一致。如果尺寸不同(比如你例子中列数从5变3、行数从10变9),
my_mat会先释放原有内存,再分配新的内存空间。 - 这时候右边的切片表达式还指向原矩阵的旧内存,而旧内存已经被释放,访问它就会触发段错误或读取垃圾数据;即使尺寸相同,也可能因为写入新数据时覆盖了还未读取的原数据,导致结果不符合预期。
为什么用临时变量就正常?
当你先把切片结果赋值给new_mat时,Eigen会立即计算切片的完整结果并存储到new_mat的独立内存中。这时候new_mat的数据和原my_mat的内存完全无关,后续再把new_mat赋值给my_mat时,不管my_mat的内存如何变化,都不会影响已经计算好的new_mat数据。
解决办法
除了用临时变量的方式,还有更简洁的方案:
- 使用
eval()方法强制Eigen立即计算切片表达式,生成独立的临时矩阵,再赋值给原变量:my_mat = my_mat(Eigen::all, sub_cols).eval(); my_mat = my_mat(Eigen::lastN(my_mat.rows() - 1), Eigen::all).eval(); - 或者用
finished()方法,效果和eval()类似,适合某些场景下明确结束表达式求值。
额外注意
哪怕切片后的矩阵尺寸和原矩阵完全相同(比如只是重新排列行/列顺序),直接赋值仍然可能因为内存重叠导致数据覆盖,建议同样使用eval()或临时变量来避免风险。
内容的提问来源于stack exchange,提问作者eaglefreeman
相关产品推荐
相关产品推荐

