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

Python ctypes调用C DLL二维数组乘法后内存释放失败求助

解决Python ctypes调用C DLL内存释放崩溃与泄漏问题

问题概述

使用Python的ctypes模块调用Visual Studio 2017编译的matrixDLL.dll执行二维数组乘法,计算结果正确,但调用free_memDyn函数释放ptrA、ptrB等内存时程序崩溃,同时担心存在内存泄漏风险。

错误原因分析

  1. 内存管理边界错误:ptrA、ptrB是Python通过ctypes创建的数组,内存由Python的垃圾回收机制管理,并非C代码中用malloc分配的内存,直接用C的free函数释放会触发非法内存访问,导致程序崩溃。
  2. C代码内存泄漏:D2_Dot函数中自行分配的二维数组A、B在计算完成后未释放,会造成内存泄漏;返回的结果数组C则需要在Python侧调用free_memDyn释放。

解决方案

  • 禁止释放Python侧创建的内存:ptrA、ptrB由Python管理,无需手动调用C的释放函数。
  • 修复C代码的内存泄漏:在D2_Dot函数中,计算完成后立即释放临时数组A、B的内存;同时处理维度不匹配的异常分支,避免内存泄漏。
  • 正确释放C返回的结果内存:为free_memDyn设置正确的参数类型,仅释放C代码返回的结果数组。

修改后的代码示例

修正后的C代码

//arrayMulti.cpp - will be packaged into "matrixDLL.dll" by Visual Studio 2017.
#include "pch.h"
#include <stdio.h>
#include <stdlib.h>

extern "C" {
    __declspec(dllexport) double** D2_Dot(double* prtA, int ay, int ax, double* prtB, int by, int bx)
    {
        //allocate memory for 2D array A and assign values
        double** A = (double**)malloc(sizeof(double*)*ay);
        for (int i = 0; i < ay; i++)
            A[i] = (double*)malloc(sizeof(double)*ax);
        for (int i1 = 0; i1 < ay; i1++)
            for (int i2 = 0; i2 < ax; i2++)
                A[i1][i2] = *(prtA + i1 * ax + i2);
        
        //allocate memory for 2D array B and assign values
        double** B = (double**)malloc(sizeof(double*)*by);
        for (int j = 0; j < by; j++)
            B[j] = (double*)malloc(sizeof(double)*bx);
        for (int j1 = 0; j1 < by; j1++)
            for (int j2 = 0; j2 < bx; j2++)
                B[j1][j2] = *(prtB + j1 * bx + j2);
            
        //allocate memory for the resulting array C
        double** C = (double**)malloc(sizeof(double*)*ay);
        for (int k = 0; k < ay; k++)
            C[k] = (double*)malloc(sizeof(double)*bx);

        if (ax != by) {
            printf("Dimension Error!!\n");
            // 维度不匹配时,释放已分配的所有内存
            for (int i = 0; i < ay; i++) free(A[i]);
            free(A);
            for (int j = 0; j < by; j++) free(B[j]);
            free(B);
            for (int k = 0; k < ay; k++) free(C[k]);
            free(C);
            return NULL;
        }
        else {
            //find the values of the resulting array C
            for (int i = 0; i < ay; i++)
                for (int j = 0; j < bx; j++)
                    for (int k = 0; k < by; k++)
                        C[i][j] += A[i][k] * B[k][j];

            // 释放临时数组A、B的内存
            for (int i = 0; i < ay; i++) free(A[i]);
            free(A);
            for (int j = 0; j < by; j++) free(B[j]);
            free(B);

            return C;
        }
    }

    __declspec(dllexport) void free_memDyn(double** ptr, int ny, int nx)
    {
        for (int f = 0; f < ny; f++)
            free(ptr[f]);
        free(ptr);
    }
}

修正后的Python代码

from ctypes import *

matrix = cdll.LoadLibrary('matrixDLL.dll')

# 设置函数参数和返回值类型
matrix.D2_Dot.argtypes = [POINTER(c_double), c_int, c_int, POINTER(c_double), c_int, c_int]
matrix.D2_Dot.restype = POINTER(POINTER(c_double))
matrix.free_memDyn.argtypes = [POINTER(POINTER(c_double)), c_int, c_int]

A = [[1.0,2.0],[3.0,4.0]]
B = [[0.0,1.0],[2.0,3.0]]
aRow = len(A)
aCol = len(A[0])
ptrA = (c_double*aCol*aRow)()
for i in range(aRow):
  for j in range(aCol):
    ptrA[i][j] = A[i][j]
    
bRow = len(B)
bCol = len(B[0])
ptrB = (c_double*bCol*bRow)()
for i in range(bRow):
  for j in range(bCol):
    ptrB[i][j] = B[i][j]

dotRes = matrix.D2_Dot(ptrA, aRow, aCol, ptrB, bRow, bCol)

if dotRes:
    arrList = [[0.]*bCol for _ in range(aRow)]
    for i in range(aRow):
        for j in range(bCol):
            arrList[i][j] = dotRes[i][j]

    # 输出结果
    print('arrList[0][0]: ', arrList[0][0])  # 4.0
    print('arrList[0][1]: ', arrList[0][1])  # 7.0
    print('arrList[1][0]: ', arrList[1][0])  # 8.0
    print('arrList[1][1]: ', arrList[1][1])  # 15.0

    # 释放C返回的结果内存
    matrix.free_memDyn(dotRes, aRow, bCol)
else:
    print("Dimension Error!!")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 04:16:02