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

VB.NET读写受保护内存错误求助:仅x64调试触发,x86正常

问题描述

调试时出现错误提示:

Attempted to read or write protected memory. This is often an indication that other memory is corrupt

在Visual Studio 2015中采用x64模式调试时触发该错误,切换为x86模式则正常。相关VB.NET代码如下:

Private Sub MenuItem1Click(ByVal sender As Object, ByVal e As EventArgs)
    GeneratePayslip()
    report.ShowPrintPreviewDialog()
End Sub

Private Sub GeneratePayslip()
    Dim dir As String = Path.GetDirectoryName(Application.ExecutablePath)
    Dim filename As String = Path.Combine(dir, "LOGO.png")
    Dim table1 As New DataTable()
    Dim table2 As New DataTable()
    Dim table3 As New DataTable()
    Dim table4 As New DataTable()
    report.Clear()
    Dim query1 = "SELECT"
    Using adapter1 As New OleDbDataAdapter(query1, con)
        adapter1.Fill(table1)
    End Using
    Dim query2 = "SELECT"
    Using adapter2 As New OleDbDataAdapter(query2, con)
        adapter2.Fill(table2)
    End Using
    Dim query3 = "SELECT"
    Using adapter3 As New OleDbDataAdapter(query3, con)
        adapter3.Fill(table3)
    End Using
    Dim query4 = "SELECT" 
    Using adapter4 As New OleDbDataAdapter(query4, con)
        adapter4.Fill(table4)
    End Using
    For i = 0 To table1.Rows.Count - 1
        If i > 0 Then
            'We are not on the first row so we need a new page.
            report.NewPage()
        End If
        Dim row1 = table1.Rows(i)
        Dim row2 = table2.Rows(i)
        Dim row3 = table3.Rows(i)
        Dim row4 = table4.Rows(i)
        Dim tableCopy1 = {row1}.CopyToDataTable()
        Dim tableCopy2 = {row2}.CopyToDataTable()
        Dim tableCopy3 = {row3}.CopyToDataTable()
        Dim tableCopy4 = {row4}.CopyToDataTable()
        report.AddDataTable(tableCopy1)
        report.AddDataTable(tableCopy2)
        tableCopy1.Columns.Clear()
        tableCopy2.Columns.Clear()
        report.AddDataTable(tableCopy3)
        tableCopy3.Columns.Clear()
        report.AddDataTable(tableCopy4)
    Next
End Sub

错误截图:
错误提示

原因分析与解决建议

核心原因

这个错误在x64模式下出现、x86正常,大概率是使用的第三方报表组件(代码中的report对象)没有64位兼容版本,或者组件的64位版本存在内存访问bug。这类错误通常是非托管代码(组件底层可能用C++等编写)在64位环境下内存地址对齐、指针处理不当导致的,和IDE本身关系不大,主要是组件兼容性问题。

另外代码里的几个潜在问题也可能加剧这个错误:

  1. 添加DataTable到报表后立刻调用Columns.Clear(),可能导致报表组件后续渲染时访问已释放的列内存,64位环境下这种野指针访问更容易触发保护内存错误。
  2. 假设table1到table4行数完全一致,但实际查询返回行数不一致时,会引发索引越界,间接触发内存错误。

解决步骤

1. 检查报表组件的64位兼容性

  • 确认报表库是否支持x64架构:如果组件只有32位版本,强制x64运行必然触发错误,此时只能保留x86编译,或更换支持64位的报表组件。
  • 若组件有64位版本,确保安装对应版本并在项目中引用64位程序集。

2. 修复代码潜在风险

  • 删除Columns.Clear()语句:报表组件需要依赖DataTable的列信息进行渲染,添加后立即清空列会导致内存引用异常,保留DataTable直到报表渲染完成后再清理。
  • 验证多表行数一致性:循环前添加检查,避免索引越界:
    If table1.Rows.Count <> table2.Rows.Count OrElse table1.Rows.Count <> table3.Rows.Count OrElse table1.Rows.Count <> table4.Rows.Count Then
        Throw New Exception("查询结果行数不一致,无法生成工资单")
    End If
    
  • 优化DataTable创建方式:用更安全的方式生成单行列DataTable:
    ' 替换原有的tableCopy1创建逻辑
    Dim tableCopy1 As DataTable = table1.Clone()
    tableCopy1.ImportRow(row1)
    

3. 调整VS调试设置

  • 右键项目→属性→调试→取消勾选“启用本机代码调试”,减少托管与非托管代码交互时的内存检测冲突。
  • 在VS选项→调试→常规中勾选“启用仅我的代码”,聚焦自身代码逻辑排查问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 10:42:40