回 帖 发 新 帖 刷新版面

主题:[讨论]关于CopyMemory的奇怪的现象

Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Private Sub Command1_Click()
Dim s1 As String
Dim s2 As String
Dim pStr As Long

s1 = "English中文"

'Test1 :OK
s2 = String$(9, 0)
CopyMemory s2, s1, Len(s1)  'lenB(s1)
'是否在Text1里显示字符,居然会影响到s1、s2的取值???!!!
Text1.Text = Text1.Text & "s2=" & s2 & ",len(s2)=" & Len(s2) & ",lenB(s2)=" & LenB(s2) & vbCrLf
Text1.Text = Text1.Text & "s1=" & s1 & vbCrLf
Debug.Print "s2="; s2, "len(s2)="; Len(s2), "lenB(s2)="; LenB(s2)   'English中文,9,18
Debug.Print "s1="; s1

'Test2 : OK
s2 = String$(9, 0)
CopyMemory pStr, ByVal VarPtr(s1), 4
'CopyMemory ByVal s2, ByVal pStr, LenB(s1)  'Engl,4,9
'CopyMemory ByVal s2, pStr, LenB(s1)    '??,3,7
'CopyMemory s2, ByVal pStr, LenB(s1)    ' ,0,0
'CopyMemory ByVal StrPtr(s2), ByVal pStr, LenB(s1)   'without StrConv() ,English中文,9,18
CopyMemory s2, pStr, LenB(s1)           'English中文,9,18
s2 = StrConv(s2, vbFromUnicode)
Text1.Text = Text1.Text & "s2=" & s2 & ",len(s2)=" & Len(s2) & ",lenB(s2)=" & LenB(s2) & vbCrLf
Text1.Text = Text1.Text & "s1=" & s1 & vbCrLf
Debug.Print "s2="; s2, "len(s2)="; Len(s2), "lenB(s2)="; LenB(s2)
Debug.Print "s1="; s1

'Test3
s2 = String$(9, 0)      '此处对s2的赋值会影响到s1 ?
CopyMemory ByVal StrPtr(s2), ByVal StrPtr(s1), LenB(s1)
Text1.Text = Text1.Text & "s2=" & s2 & ",len(s2)=" & Len(s2) & ",lenB(s2)=" & LenB(s2) & vbCrLf
Text1.Text = Text1.Text & "s1=" & s1 & vbCrLf
Debug.Print "s2="; s2, "len(s2)="; Len(s2), "lenB(s2)="; LenB(s2)
Debug.Print "s1="; s1       's2是否重新赋值,以及是否在Text1里显示,似乎会影响到s1的值!!!莫名其妙
End Sub

copymemory的正确使用方法是怎样的?
字符串拷贝时如果用copyMemory我一直都是下面这样用的。
CopyMemory s2, s1, Len(s1)  'lenB(s1)

回复列表 (共6个回复)

沙发

网上看到的。
'用指针的做法SwapPtr 
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _ (Destination As Any, Source As Any, ByVal Length As Long) 

Sub SwapPtr(sA As String, sB As String) 
 Dim lTmp As Long 
 CopyMemory lTmp, ByVal VarPtr(sA), 4 
 CopyMemory ByVal VarPtr(sA), ByVal VarPtr(sB), 4 
 CopyMemory ByVal VarPtr(sB), lTmp, 4 
End Sub  

板凳

[quote]
CopyMemory pStr, ByVal VarPtr(s1), 4
……
CopyMemory s2, pStr, LenB(s1)           'English中文,9,18   
……
s2 = String$(9, 0)      '此处对s2的赋值会影响到s1 ?

[/quote]
CopyMemory s2,pStr,lenb(s1)     从一个长整型拷18个数据到一个字符串?

我很奇怪为什么类似CopyMemory s2, s1, Len(s1)这样的用法不会错,而这句改为CopyMemory s2,byval pStr, 4还是不行,但这句肯定有问题了


改法1:

CopyMemory pStr, ByVal VarPtr(s1), 4
……
s2=space(len(s1))
CopyMemory ByVal StrPtr(s2), ByVal pStr, LenB(s1) '只复制内容



改法2:

CopyMemory byval varptr(pStr), ByVal VarPtr(s1), 4
……
s2=space(len(s1))
CopyMemory ByVal varPtr(s2),  pStr, 4 '复制地址,s1、s2指向同一字符串

msgbox s1 &","& s2
mid$(s1,1,1)="F"'地址不变
msgbox s1 &","& s2
s1="12345"
msgbox s1 &","& s2'原地址 strptr(s1)=strptr(s2)成了乱码 ,strptr(s1)有了新地址









我用CopyMemory一直这样用的
copymemory byval strptr(strD),byval strptr(strS),lenb(strS)
copymemory byval varptr(strD),byval varptr(strS),4
copymemory byval varptr(LongD),byval varptr(LongS),4
copymemory byval varptr(IntD),byval varptr(IntS),2
copymemory LongD,LongS,4 '只知道这样没问题

copymemory byval objptr(ObjD),byval objptr(ObjS),4

还不知道这样居然不出错 CopyMemory s2, s1, Len(s1)







曾写了个DLL在VB中用

__declspec(dllexport) int WINAPI abc(int path)
{
    return path;//就是输出整数path的值
}




Private Declare Function ABC Lib "Try1.dll" Alias "?abc@@YGHH@Z" (Path As Any) As Long
dim a as string,b as long
a="1234"
b=1234
msgbox Str(ABC(b))
msgbox Str(ABC(ByVal VarPtr(a)))
msgbox Str(ABC(ByVal StrPtr(a)))
msgbox  Str(ABC(VarPtr(a)))
msgbox  Str(ABC(StrPtr(a)))
msgbox Str(ABC(a))

msgbox Str(ABC(b))可以看出,整数可以直接使用,完全正确。Path As Any和Byval Path As Long都一样
但字符串msgbox Str(ABC(a))则不知道得了什么乱七八糟的值,所以我一直不敢直接用CopyMemory s2, s1, Len(s1),没想到居然可以

大虾们能否解释下这是怎么回事?

3 楼

[quote]
msgbox Str(ABC(ByVal VarPtr(a)))
msgbox Str(ABC(ByVal StrPtr(a)))
msgbox  Str(ABC(VarPtr(a)))
msgbox  Str(ABC(StrPtr(a)))
[/quote]
不知道显示的结果还是不是“1234” ?
而且,似乎这个例子与copymemory不相关?

4 楼

不是了,结果就等于VarPtr(a)和 StrPtr(a)

ABC是为了看看
copymemory s1,s2,len(s2)
copymemory byval strptr(s1),byval strptr(s2),lenb(s2)
copymemory byval varptr(s1),byval varptr(s2),4
(就是使用了Any定义之后)

这3种方法前2个参数传递过去的值有什么不同,
我想知道的是msgbox Str(ABC(a))得到的究竟是什么

5 楼

好像以前在哪里看过定义成any更有效率而long更安全,如果定义成long就只能用后2种方法 就没这么多问题了

6 楼

用定长字符串试试
rtlmovememory 要精确计算好要复制的字节

我来回复

您尚未登录,请登录后再回复。点此登录或注册