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

打印转置矩阵时触发内存访问错误的排查求助

矩阵转置汇编函数引发内存访问错误的问题

我在打印转置后的矩阵第一行时出现了内存访问不可用的错误,麻烦帮忙排查问题出在哪里——是C++代码的问题,还是汇编函数的问题?

调用汇编函数的C++代码

#include <iostream>
#include <windows.h>

extern "C" void transpose(INT64**, INT64);

// 打印矩阵的函数
void printMatrix(INT64** matrix, INT64 n) {
    for (INT64 i = 0; i < n; ++i) {
        for (INT64 j = 0; j < n; ++j) {
            std::cout << matrix[i][j] << " ";
        }
        std::cout << std::endl;
    }
}

int main() {
    INT64 n = 8; // 矩阵大小

    // 初始化矩阵A
    INT64** A = new INT64 * [n];
    for (INT64 i = 0; i < n; ++i) {
        A[i] = new INT64[n];
        for (INT64 j = 0; j < n; ++j) {
            A[i][j] = i * n + j; // 填充矩阵A
        }
    }

    std::cout << "转置前的矩阵:" << std::endl;
    printMatrix(A, n); // 打印转置前的矩阵

    // 调用转置函数
    transpose(A, n);

    std::cout << "转置后的矩阵:" << std::endl;
    printMatrix(A, n); // 打印转置后的矩阵

    // 释放内存
    for (INT64 i = 0; i < n; ++i) {
        delete[] A[i];
    }
    delete[] A;

    return 0;
}

汇编实现的transpose函数

; TransposeSquareMatrix(A, n)
    mov     rdi, rcx
    mov     rsi, rdx
    mov     rbx, rdi        ; Address A is in RDI
    mov     rcx, rsi        ; Dimension n is in RSI
    imul    r8, rsi, 8      ; Step between rows
    dec     rcx
    jz      .c              ; It's a (1 x 1) matrix
.a: push    rcx             ; (1)
    mov     rsi, rbx        ; Column address
    mov     rdi, rbx        ; Row address
.b: add     rsi, 8          ; To next element in this row
    add     rdi, r8         ; To next element in this column
    mov     rax, [rsi]      ; Swap 2 elements
    mov     rdx, [rdi]
    mov     [rdi], rax
    mov     [rsi], rdx
    dec     rcx
    jnz     .b
    lea     rbx, [rbx + r8 + 8] ; To next element on main diagonal
    pop     rcx             ; (1)
    dec     rcx
    jnz     .a              ; Continu until (1 x 1) matrix
.c: ret

问题根源分析

核心问题是汇编代码的内存模型和C++创建的矩阵不匹配:

  • C++里你创建的是INT64**类型的指针数组式矩阵,每一行的内存是独立分配的(new INT64[n]),行与行之间的物理内存不一定连续,甚至可能完全分散。
  • 但你的汇编代码默认矩阵是连续的一维内存块(比如栈上直接分配的INT64 A[8][8]),用imul r8, rsi, 8计算行间距,然后用add rdi, r8跳转下一行——这会直接访问到错误的内存地址,触发内存访问越界错误。

另外,你的汇编循环逻辑也有问题:循环计数的递减逻辑会导致交换次数超出矩阵的上三角范围,不过这是次要问题,先解决内存模型不匹配的问题才能正常运行。

修正思路

要处理INT64**类型的矩阵,汇编里必须先通过指针数组拿到每行的实际地址:

  1. 从传入的矩阵指针rdi中,取出第i行的地址:mov r10, [rdi + i*8](因为每个行指针是8字节)。
  2. 再从该行地址中取出第j列的元素:mov rax, [r10 + j*8]。
  3. 转置时需要交换A[i][j]和A[j][i],所以要分别拿到这两个元素的实际内存地址,再执行交换操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 10:10:54