You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VS内嵌汇编实现集合差运算时遭遇读访问违例问题求助

问题根源与修复方案

核心错误分析

  1. 非法指针起始位置
    int* ptr1 = arr1.data() - 1; 和 int* ptr2 = arr2.data() - 1; 直接指向vector缓冲区的前一个内存地址,属于未定义行为,后续指针偏移操作极易触发内存访问越界。

  2. _delete分支的致命逻辑错误
    在_delete标签下执行loop _array2完全违背预期:loop指令依赖ecx寄存器的计数,此时ecx是arr1剩余的遍历次数,跳转到_array2会导致指针、计数器彻底混乱,直接引发读访问违例,这就是你看到ptr1变成0xFFFFFFD7(-41的补码,明显越界的指针值)的原因。

  3. 未正确统计删除次数与更新vector状态
    numberOfDeletes全程未递增,且手动修改内存后未调用vector的resize()或erase()来更新内部的size和缓冲区状态,导致vector的内部数据与实际内存状态不匹配。

  4. 元素删除的逻辑漏洞
    当前删除逻辑仅用下一个元素覆盖当前元素,未完成后续所有元素的前移操作,无法真正实现元素删除。


修正后的代码

以下是修复了上述问题的实现,同时保留内嵌汇编的逻辑:

#include <vector>
using namespace std;

int main() {
    vector<int> arr1 = {8, 3};
    vector<int> arr2 = {7, 8};
    int* ptr1 = arr1.data(); // 直接指向vector的起始地址
    int size1 = arr1.size();
    int* ptr2 = arr2.data();
    int size2 = arr2.size();
    int numberOfDeletes = 0;

    __asm {
        mov ebx, ptr2
        mov edx, 0                  ; arr2的遍历索引
    _array2:
        cmp edx, size2
        je _out                     ; 遍历完arr2就退出
        mov esi, dword ptr[ebx]     ; 取出arr2当前元素
        mov eax, ptr1
        mov ecx, size1
        sub ecx, numberOfDeletes    ; 排除已删除的元素,实际遍历长度
    _comparing:
        cmp dword ptr[eax], esi
        je _delete                  ; 找到匹配元素,执行删除
        add eax, 4
        loop _comparing
        ; 没找到匹配,移动到arr2下一个元素
        add ebx, 4
        inc edx
        jmp _array2

    _delete:
        ; 从当前位置开始,将后续元素依次前移
        mov edi, eax
    _shift_elements:
        mov ebp, dword ptr[edi + 4]
        mov dword ptr[edi], ebp
        add edi, 4
        cmp edi, ptr1 + (size1 - numberOfDeletes) * 4
        jl _shift_elements
        inc numberOfDeletes         ; 统计删除次数
        ; 删除后,继续检查当前位置(因为前移后的元素可能也匹配)
        jmp _comparing

    _out:
        ; 更新vector的实际大小
        mov size1, size1 - numberOfDeletes
    }

    ; 让vector同步内部状态
    arr1.resize(size1);
    return 0;
}

额外注意事项

  • 不要直接操作vector的原始指针并修改内存,除非你非常清楚vector的内存布局;优先使用vector提供的erase()、remove()等成员函数,安全性和可维护性更高。
  • 内嵌汇编在现代C++中属于不推荐的写法,尤其是在64位环境下兼容性极差;如果必须使用汇编,建议单独写成函数而非内嵌。

内容的提问来源于stack exchange,提问作者Ruslan Vaitukevich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 15:07:10