C++ Delphi 2007 EXE和C++;DLL:调试输出:027D4FF8处的堆块在027D5009处修改,超出了请求的9进程大小
我试图在Delphi 2007中执行导入的函数: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
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
类型是COMBSTR
字符串的包装器,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
,等等),那么Delphi代码可以直接调用相应的内存释放函数(CoTaskMemAlloc()
/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';