用VarPtr传给CopyMemory拷贝字符串 为啥结果不正确

slowgrace 2009-09-01 09:52:22
加精
Option Explicit

Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(pDest As Any, pSource As Any, ByVal byteLen As Long)

Sub test2()
Dim String1 As String
Dim String2 As String
Dim pString1 As Long

String1 = "PowerVB"
String2 = String$(7, 0)

'Try three: Get the string's pointer from VarPtr
CopyMemory pString1, ByVal VarPtr(String1), 4
CopyMemory ByVal String2, ByVal pString1, 14

Debug.Print String2 '得到的不是PowerVB,而是“P o w e”?为什么?
End Sub


slowgrace
2 分钟前

以下为本帖小结 ==================================================
谢谢许多朋友热心回复,尤其是赵老虎的全程指点和陈辉版主的推荐!我觉得这个帖子信息量挺大的,想了解VB6对API函数的字符串参数处理机制的同学可以仔细看一看。后来的朋友推荐按以下顺序看:
基础知识:196楼+197楼;187楼+222楼;184楼+189楼;30+31楼;88楼+119楼+这个帖子的17楼+25楼;35+36+39楼;74楼+78楼;118楼;160楼;191楼+192楼
例1:194楼+198楼;
例2:0楼+90楼+210楼
例3:229楼
例4:16楼+162楼+132楼+184楼+246楼
例5:10楼+248楼+252楼
例6:34楼+40楼+92楼+125楼
例7:129楼+130+134+141+143+269+276


或者看我在博客里写的小结:()、()、()、()。
...全文
4356 293 打赏 收藏 转发到动态 举报
写回复
用AI写文章
293 条回复
切换为时间正序
请发表友善的回复…
发表回复
supertankhzt 2012-05-06
  • 打赏
  • 举报
回复
好贴啊!研究了二天,受益匪浅。
ldfaltxj 2010-09-16
  • 打赏
  • 举报
回复
学习了,不错
特别 2009-11-23
  • 打赏
  • 举报
回复
楼主这个小结做的挺厚道的
slowgrace 2009-10-23
  • 打赏
  • 举报
回复
复习一遍,结帖了。

谢谢各位朋友热心回复。

为了方便后来的朋友,我这样给分的:
(1)比较重要的结论性的东西给分较高;
(2)给出代码的都给了2分,注意这些代码有不少是错误的,但是通过分析这些代码的错误可以用来帮助熟悉巩固所学到的知识(见273楼)。
slowgrace 2009-09-16
  • 打赏
  • 举报
回复
灰常感谢。我先试试,如果有问题,另外开帖请教。
Tiger_Zhao 2009-09-16
  • 打赏
  • 举报
回复
无论大小,反正代码块数不多,推荐用 TextPad
1)首先当然是设好 VB 的语法高亮。
2)如果你嫌新建文档通过属性选语法麻烦,可以用一个空白的 .bas 文件作为粘贴的文档
3)粘贴代码
4)★全选,然后在编辑菜单中选“其他复制\作为 HTML 页面”
5)不需要完整的 HTML 页面内容,粘贴到一个新的文档中
6)如果 Blog 不支持自定义样式,你就将里面的 <span class="..."> 替换为 <font color="..">,这可以录个宏,以后执行一下就可以了。
7)将内容部分的 HTML 段落复制出来就能用了。
slowgrace 2009-09-16
  • 打赏
  • 举报
回复
你眼真尖
slowgrace 2009-09-16
  • 打赏
  • 举报
回复
大段的代码着色我用的是CSDN博客编辑器带的语法高亮工具
小段的代码着色我用的是Live Writer的语法高亮插件

这两个工具都不能语法高亮Debug.Print
小写的 as long 没有着色,这个是CSDN工具的显示结果。
Tiger_Zhao 2009-09-16
  • 打赏
  • 举报
回复
[Quote=引用 278 楼 slowgrace 的回复:]或者看我在博客里写的小结:(一)、(二)、(三)、(四)。[/Quote]
你用什么代码着色工具,Debug.Print 没有着色,小写的 as long 也没有着色,难道是 Pretty Code?
slowgrace 2009-09-16
  • 打赏
  • 举报
回复
谢谢楼上各位夸奖!谢谢豆子版主及其他各位版主帮助置顶小结!
zzyong00 2009-09-15
  • 打赏
  • 举报
回复
非常精彩的论文!!赞一下!
嗷嗷叫的老马 2009-09-15
  • 打赏
  • 举报
回复
[Quote=引用 279 楼 chenhui530 的回复:]
刚才我去你博客看了下,西西够强,是我是没那么多心事去编辑排版之类的
这样做方便后来学习的爱好者,我的博客为了偷懒几乎全是贴代码
[/Quote]
你的文章一读就要出人命------------------从不写标点的家伙
嗷嗷叫的老马 2009-09-15
  • 打赏
  • 举报
回复
[Quote=引用 279 楼 chenhui530 的回复:]
刚才我去你博客看了下,西西够强,是我是没那么多心事去编辑排版之类的
这样做方便后来学习的爱好者,我的博客为了偷懒几乎全是贴代码
[/Quote]
你的文章一读就要出人命------------------从不写标点的家伙
chenhui530 2009-09-15
  • 打赏
  • 举报
回复
刚才我去你博客看了下,西西够强,是我是没那么多心事去编辑排版之类的
这样做方便后来学习的爱好者,我的博客为了偷懒几乎全是贴代码
slowgrace 2009-09-15
  • 打赏
  • 举报
回复
或者看我在博客里写的小结:()、()、()、()。
slowgrace 2009-09-15
  • 打赏
  • 举报
回复
以下为本帖小结
==================================================
谢谢许多朋友热心回复,尤其是赵老虎的全程指点!我觉得这个帖子信息量挺大的,想了解VB6对API函数的字符串参数处理机制的同学可以仔细看一看。后来的朋友推荐按以下顺序看:

基础知识:196楼+197楼;187楼+222楼;184楼+189楼;30+31楼;88楼+119楼+这个帖子的17楼+25楼;35+36+39楼;74楼+78楼;118楼;160楼;191楼+192楼
例1:194楼+198楼;
例2:0楼+90楼+210楼
例3:229楼
例4:16楼+162楼+132楼+184楼+246楼
例5:10楼+248楼+252楼、
例6:34楼+40楼+92楼+125楼
例7:129楼+130+134+141+143+269+276

或者看我在博客里写的小结:(<a href="http://blog.csdn.net/slowgrace/archive/2009/09/14/4549926.aspx" target="_blank">一</a>)、(<a href="http://blog.csdn.net/slowgrace/archive/2009/09/14/4550116.aspx">二</a>)、(<a href="http://blog.csdn.net/slowgrace/archive/2009/09/14/4550293.aspx" target="_blank">三</a>)、(<a href="http://blog.csdn.net/slowgrace/archive/2009/09/14/4550530.aspx" target="_blank">四</a>)。
Tiger_Zhao 2009-09-14
  • 打赏
  • 举报
回复
[Quote=引用 269 楼 slowgrace 的回复:]那这么说,像我下面这样的用法都是错误的?都会导致重复释放Stirng1的内存和String2原来的内存泄露?[/Quote]
(1)适用于声明的函数中参数为 As String 时,不能在 As Any 时使用。
(2)和(3):String1 原先的字符串指针丢失而导致内存泄漏,而 String1 和 String2 同时引用一个字符串会导致重复释放、可能引发崩溃。
嗷嗷叫的老马 2009-09-13
  • 打赏
  • 举报
回复
帮你断...............
slowgrace 2009-09-13
  • 打赏
  • 举报
回复
出错的方式主要有两种:一种出错的方式是直接拷贝字符串缓冲区指针;还一种出错的方式是无意中把字符串指针当做缓冲区指针用。

这两种方式的错都很隐蔽,因为都能得到正确的结果,但是后果可能很严重。
slowgrace 2009-09-13
  • 打赏
  • 举报
回复
除了上面详细讨论过的,还有许多朋友给出了自己的修正代码,感谢各位。综述如下:

8楼-蚜虫,正确。
这个实际是对0楼代码的直接修正。先扩充String2的长度以确保对应的_tmp2长度足够;最后再做UA转换以抵消VB多做的一次AU转换。

9楼-阿勇,正确。
不经过UA/AU转换,直接拷贝字符串缓冲区。

12楼-lor12,正确。
不经过UA/AU转换,直接拷贝字符串缓冲区。

15楼-赵老虎(1),正确。
目的和源同时做UA/AU转换,直接拷贝字符串缓冲区。

15楼-赵老虎(2),正确。
不经过UA/AU转换,直接拷贝字符串缓冲区。

22楼-珠珠,错误。
同10楼。见248楼解释。

23楼-Veron,错误。
同10楼。见248楼解释。

38楼-坏上帝,正确。
直接传递字符串参数要得到正确结果,很重要的一点是要算对字节数。坏上帝专门写了个函数来算ASCI字符串所占的字节数,所以能够得到正确的结果。不过的话,我觉得这个GetStringLength函数完全可以简化为这一条语句:LenB(StrConv("我有点slow", vbFromUnicode))

46楼-陈辉,正确。
同15楼第一种方法。

50楼-陈辉(1),正确。
同8楼。

50楼-陈辉(2),正确。
同15楼第一种方法。(但解释不完全准确:)

57楼-陈辉,正确。
这个其实同15楼第一种方法,但是更通用。在直接传字符串参数的时候,要用ANSI字符串来计算字节。

58楼-陈辉,不完全正确。
String2的初始化长度取为Len(String1)就可以了。

62楼-陈辉,正确。
用ByVal VarPtr(ByVal String1),呵呵,真够绕的。

129楼-陈辉,错误。
拷贝字符串缓冲区指针会导致重复释放内存。见134,141楼解释。

165楼-(stt505249046),正确。同9楼。
但使用了Len和LenB函数,使得代码更通用了。

231楼-老张,错误。
拷贝字符串缓冲区指针会导致重复释放内存和内存泄露。见134,141楼解释。

237楼-阿勇,错误。
拷贝字符串缓冲区指针会导致重复释放内存和内存泄露。见134,141楼解释。
加载更多回复(269)

7,763

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧