Delphi处理拖拽文件调用TDirectory.GetFiles出现栈溢出问题咨询
问题1:移除末尾#0的第二个SetLength操作是否必须?
是必须的。
Delphi的string类型采用长度前缀标识内容长度,不会自动识别忽略末尾的#0空字符。你从DragQueryFile获取的路径末尾带#0时,相当于路径字符串本身包含了不可见的空字符,TDirectory.GetFiles底层处理路径递归遍历的逻辑会把这个空字符当成有效路径字符处理,触发递归逻辑异常最终导致栈溢出。
问题2:第一次调用SetLength时是否可以直接用NameLen - 1作为参数?
绝对不可以。DragQueryFile是Win32标准API,要求传入的缓冲区大小必须足够容纳路径内容+末尾的#0结束符。如果你直接分配NameLen -1的长度,缓冲区空间不足,API写入时会发生缓冲区溢出,会直接导致内存损坏、程序崩溃等更严重的问题。
问题3:更规范的处理方案有哪些?
有3种常用的稳妥方案:
- 简化现有写法:不需要调用
StrLen,因为NameLen本身就是DragQueryFile返回的实际路径字符数+1,直接在调用完API后执行SetLength(CurrFile, NameLen - 1)即可,效率更高也不会出错。 - 用临时字符数组做缓冲区:避免直接修改字符串长度,示例代码如下:
var Buf: TCharArray; begin NameLen := DragQueryFile(hDrop, i, nil, 0); SetLength(Buf, NameLen + 1); DragQueryFile(hDrop, i, PWideChar(@Buf[0]), Length(Buf)); CurrFile := string(PWideChar(@Buf[0])); end;
- 使用VCL封装好的工具类:高版本Delphi可以直接引用
Vcl.Shell单元,使用TDragFileInfo类直接获取拖拽文件路径,不需要手动处理缓冲区和空字符问题,代码更简洁可维护性更高。
内容的提问来源于stack exchange,提问作者AlexV
相关产品推荐
相关产品推荐

