报错VC\Tools\MSVC\14.27.29110\include\xmemory Line: 141 Expression: invalid argument解决方案

今天在用vs2019跑代码的时候遇到了一个很奇怪的问题,没有改动过的代码块,在之前运行都是可以成功跑通的,但是今天一跑就报错,有点莫名其妙。上报错信息:

在这里插入图片描述
没什么有用信息,只知道了错误出现在xmemory这个文件里,看文件名大概就是内存的问题了,于是我定位到了错误的地方:

在这里插入图片描述
注释信息说:If the following asserts, it likely means that we are performing an aligned delete on memory coming from an unaligned allocation. 说实话没太看懂。下面直接上我定位到的出错的代码段吧:

在这里插入图片描述

先简要介绍一下这个函数。它的作用是将siftgpu类型的关键点转换成opencv类型关键点,在这段代码中,也就是把keys中的x,y赋值到cvKeys中而已,很简单。为了让大家更好地读懂这段代码,我在这里再简单说一下代码段中每个变量的含义:

  • 输入:std::vector<std::vector<SiftGPU::SiftKeypoint >> keys,keys[i][j]表示第i张照片第j个特征点
  • 输出:std::vector<std::vector<cv::KeyPoint >> cvKeypoints,含义同keys,但是特征点是opencv类型的
  • tfcip->cvkeys和cvKeypoints的类型一样,都是std::vector<std::vector<cv::KeyPoint >>类型的。我的这个函数不是把cvKeypoints算好后直接return出去的,是通过一个单独的存储数据的类的一个指针tfcip进行传递的。

好了,代码就解释到这里,下面说说问题产生及解决。

我在第17行:cvKeypoints.push_back(cvKeys);加了断点,运行到这里之后,一个F10,到18行的}这,再一个F10,就报错了。也就是说外层这个for循环只运行了一次,而按照传入的数据,我传入了3张图片,这个for应该运行3次才对的。

我检查了所有的变量,keys传入的数据没有问题,而for循环里所有的变量又都是局部变量,所以按理说不应该是指针方面出了问题。一顿尝试过后,依旧未果。这就很奇怪了,本该循环三次的for,结果每次都是循环一次后就报错,没法进行下一次循环。

下面直接说解决方案吧(是我的师兄找出的问题所在,非常感谢!)问题原因就在于,我在第26行的时候,直接用一个等号对std::vector<std::vectorcv::KeyPoint >类型的值进行拷贝。这里就有点问题了,一个双层的vector,它是怎么通过等号进行赋值拷贝的呢?(其实这里面有点难说清楚,具体机制我也没去深究,但是这样赋值确实不太安全,虽然刚开始我这么用都是可以的,但是正如这回它突然就报错了,所以最好还是不要这么使用。)

其实大家应该还有个疑问,为什么我在debug的时候报错的明明是9 ~ 18行的那个for循环,但是我却说最终的问题是出在第26行了。这个其实我也不清楚具体的机制,毕竟9 ~ 18行的那个for循环,你拿给谁看也看不出它到底有啥问题了(所以这也是我以及另一个和我debug的师兄没有找出来问题所在的原因)。

话不多说,直接上修改后的代码:

在这里插入图片描述

修改的内容主要是,将结果通过引用的方式进行了传递,而不是用一个函数体内的双层vector局部变量进行临时存储,然后直接拷贝出来或者return。在第15行的时候,每个点的数据都是直接写到引用变量里进去的,这样就直接把数据存到目标地址去了,不需要对庞大的数据进行拷贝,也不用临时变量来占用内存,一举两得。

我把其他类的函数也都改成了这种方式的,然后就再也不会报错了。虽然遇到bug很让人头秃,但是经过这么一遭,我感觉自己的代码更规范了,代码能力也提升了,还是很开心滴~