【问题标题】:I am getting this ERROR: AddressSanitizer: negative-size-param: (size=-8)我收到此错误:AddressSanitizer:negative-size-param: (size=-8)
【发布时间】:2020-11-18 08:29:14
【问题描述】:

从给定数组中删除给定元素时,我不断收到错误消息。

这是我的代码,我不确定错误在哪里:

int removeElement(vector<int>& nums, int val) {
        int i=0;
        int size=nums.size();
        if(size <=0){
            return 0;
        }
        for(int x : nums){
            if(x==val){
                nums.erase(nums.begin() + i );
            }
            i=i+1;   
        }
        int size1=nums.size();
        return size1;
    }

然后我收到此错误:

=================================================================
==33==ERROR: AddressSanitizer: negative-size-param: (size=-8)
    #8 0x7f3d479c882f  (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
0x603000000060 is located 0 bytes to the right of 32-byte region [0x603000000040,0x603000000060)
allocated by thread T0 here:
    #6 0x7f3d479c882f  (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
==33==ABORTING

【问题讨论】:

标签: c++ arrays vector stl erase-remove-idiom


【解决方案1】:

这个循环:

for(int x : nums){

是使用迭代器在向量上循环的语法糖。

nums.erase(nums.begin() + i );

这会使当前迭代器(以及当前元素右侧元素的迭代器)无效。使用迭代器,例如递增它会导致未定义的行为。

一旦到达循环体的末尾,当前迭代器就会递增。程序的行为未定义。


您需要做的是使用std::remove_if 将剩余元素移动到向量的开头,然后使用接受一对迭代器的重载擦除末尾的元素(被移动的)。这称为擦除删除习语。

【讨论】:

  • std::remove_if 不会将元素移动到容器的末尾。数据移动是好的元素被移动到左边以覆盖“删除”的元素。新逻辑结束后的元素具有未指定的值。
  • @Blastfurnace 没错,技术上。无论如何,从抽象的角度来看,最终状态是相同的:剩余元素在开头,要擦除的元素在结尾。只是被移除的元素并不能保证完好无损,这对调用者来说并不重要,因为它们即将被删除。
  • 我之所以提到它,是因为似乎有一个普遍的误解,即std::remove(和std::remove_if)就像一个分区算法。很多人重复“删除的元素被移到最后”,如果他们依赖这种行为,他们会感到惊讶。
  • @Blastfurnace 感谢您提及。虽然我“知道”remove 做了什么,但“错误”的算法更加直观,以至于在我试图解释它时会突然出现。
猜你喜欢
  • 2018-06-09
  • 1970-01-01
  • 2020-09-24
  • 1970-01-01
  • 2022-07-22
  • 2017-04-05
  • 2015-10-12
  • 2013-07-28
  • 2021-09-04
相关资源
最近更新 更多