Delphi 2007 EXE和C ++ DLL:调试输出:在027D4FF8处的堆块修改在027D5009过去请求的大小为9 Process

时间:2017-10-27 17:20:52

标签: c++ delphi dll heap

我正在尝试在Delphi 2007中执行导入的函数:

function getOfficialCardNumber(): WideString ; cdecl; external 'idcapp.dll';

但几秒后(在调试配置中)它停在这里:

77BD37D6 C6055562C17700   mov byte ptr [$77c16255],$00

并说:

Debug Output: Heap block at 027D4FF8 modified at 027D5009 past requested size of 9  Process PreglediZaDom.exe (23672)

提到的函数是用C ++(Visual Studio)编写的

我尝试将WideString更改为PWideString等,但没有成功。有谁知道什么是问题?

在类似的应用程序中,但用VB6编写,他们给了我这个函数来转换字符串:

Public Function pisBstrToString(bstr) As String

    Dim bArray()    As Integer

    Dim longArray() As Long

    Dim str         As String

    Dim i           As Integer

    bArray = pisStringToBArray(bstr)
    longArray = pisBArrayToLongArray(bArray)

    str = ""

    For i = 1 To UBound(longArray)

        If longArray(i) > 0 And longArray(i) < 256 Then
            str = str & Chr(longArray(i))
        Else
            str = str & pisLongToUnichar(longArray(i))
        End If

    Next i

    pisBstrToString = str

End Function

我现在知道用C ++编写的函数是这样导出的:

BSTR _stdcall getOfficialCardNumber()

1 个答案:

答案 0 :(得分:1)

VB6不支持cdecl,仅支持stdcall。就在那里,你在Delphi代码中使用了错误的调用约定,导致调用堆栈管理不善。

Delphi的WideString类型是COM BSTR字符串的包装,VB6确实用于它自己的字符串 - 但不是外部DLL函数的String返回值!即使VB6期望/接受BSTR作为输出,DLL函数也将返回BSTR cpu寄存器中的EAX指针,就像大多数其他返回类型一样。但是,在将EAX作为返回类型处理时,Delphi不使用WideString。它作为隐藏的var参数传递。看到 Why can a WideString not be used as a function return value for interop?了解更多详情。

如果DLL函数返回char*指针,则必须将函数返回值声明为PAnsiChar

function getOfficialCardNumber(): PAnsiChar; stdcall; external 'idcapp.dll';

否则,如果它返回wchar_t*指针 1 ,则必须将函数返回值声明为PWideChar

function getOfficialCardNumber(): PWideChar; stdcall; external 'idcapp.dll';

无论哪种方式,您还有另一个问题需要处理 - 谁拥有指向的内存,以及如何释放它? Delphi不能直接释放DLL返回的内存,那么内存是如何分配的呢?

  • 如果在DLL中静态,则根本不需要释放它。

  • 如果动态,哪个内存管理器分配了它?

    • 如果它是DLL内部的内存管理器,那么DLL在完成使用后必须导出一个单独的函数来接收指针,以便可以使用相同的内存管理器释放它。

    • 如果是OS提供的内存API(LocalAlloc() / GlobalAlloc()IMalloc.Alloc()imalloc / CoTaskMemAlloc()等),那么Delphi代码可以直接调用相应的记忆释放功能(LocalFree() / GlobalFree()IMalloc.Free() / CoTaskMemFree()等)。

1 :如果发生实际上是BSTR指针,则需要将返回的指针传递给SysFreeString()使用它完成。