C++ Delphi 2007 EXE和C++;DLL:调试输出:027D4FF8处的堆块在027D5009处修改,超出了请求的9进程大小

C++ Delphi 2007 EXE和C++;DLL:调试输出:027D4FF8处的堆块在027D5009处修改,超出了请求的9进程大小,c++,delphi,dll,heap,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 re

我试图在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++(VisualStudio)

编写 我曾尝试将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

VB6不支持
cdecl
,仅支持
stdcall
。因此,您在Delphi代码中使用了错误的调用约定,导致调用堆栈管理不当

Delphi的
WideString
类型是COM
BSTR
字符串的包装器,VB6将其用于自己的字符串,但不用于外部DLL函数的
string
返回值!即使VB6期望/接受一个
BSTR
作为输出,DLL函数也会像大多数其他返回类型一样,返回
EAX
cpu寄存器中的
BSTR
指针。但是,在处理
WideString
时,Delphi不使用
EAX
作为返回类型。它作为隐藏的
var
参数传递。看见 更多细节

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

function getOfficialCardNumber(): PAnsiChar; stdcall; external 'idcapp.dll';
否则,如果它返回一个
wchar\u t*
指针1,则必须将函数返回值声明为
PWideChar

function getOfficialCardNumber(): PWideChar; stdcall; external 'idcapp.dll';
无论哪种方式,您都有另一个问题要处理——谁拥有被指向的内存,以及如何释放它?Delphi不能直接释放DLL返回的内存,那么内存是如何分配的呢

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

  • 如果是动态的,是哪个内存管理器分配的

    • 如果是DLL内部的内存管理器,则DLL必须在使用完指针后导出单独的函数以接收指针,以便使用相同的内存管理器将其释放

    • 如果它是操作系统提供的内存API(
      LocalAlloc()
      /
      GlobalAlloc()
      IMalloc.Alloc()IMalloc
      /
      CoTaskMemAlloc()
      ,等等),那么Delphi代码可以直接调用相应的内存释放函数(
      LocalFree()
      /
      GlobalFree()
      IMalloc.Free()
      /
      CoTaskMemFree()
      等)



1:如果它实际上是一个
BSTR
指针,那么在使用完它之后,您需要将返回的指针传递给
SysFreeString()

可能翻译错误?C或C++头中声明的函数是怎样的?或者VB6中声明的函数是怎样的?我没有C++头(DLL是由别人构建的)。公共声明函数getOfficialCardNumber Lib“C:\WINDOWS\system32\idcapp.dll”()由于字符串是VB6中的声明,我怀疑VB6能否处理
cdecl
,因此它可能应该是
stdcall
。结果可能是一个
WideString
确实如此。自从我与VB6接口以来已经有很长一段时间了,所以以下可能是错误的:尝试PWideChar而不是WideString。一定要用SysFreeString.FWIW来释放结果,如果人们写了一个DLL(不管是哪种语言),他们应该为它提供一个C或C++头。我对编写dll的看法:在这个dll中有一个叫做login:procedure-login(uName,pwd:WideString)的过程;cdecl;外部“idcapp.dll”;如果我这样声明:过程登录(uName,pwd:String);cdecl;外部“idcapp.dll”;它不会工作,所以参数必须是WideString类型,所以我认为返回参数也应该是WideString,是的,它在Delphi的EAX寄存器
字符串中停止。当涉及互操作时,不能切换它们。如果DLL函数需要一个
宽字符串
,请向其传递一个
宽字符串
。但是您确定它实际上不需要一个
PWideChar
?DLL是用Delphi编写的吗?还是其他的?DLL是用C++编写的,我不知道它们作为返回类型使用什么,我会在明天的时候向他们请求一个标题,除非<代码> Login()<代码>被声明为接受<代码> BSTR < /Cube >参数,在Delphi中,你不应该声明它为<代码> WordSoist。对于
char*
使用
PAnsiChar
,对于
wchar*
使用
PWideChar
。在后一种情况下,您可以使用
WideString
变量,只需在传递它时将其强制转换为
PWideChar
function getOfficialCardNumber(): PWideChar; stdcall; external 'idcapp.dll';