CreateDir 在 QB64 中抛出异常
CreateDir throws exception in QB64
我有以下代码,有时 returns 在尝试创建新目录时出错。有时当该目录不存在时,它会抛出错误并且不会创建该目录。我想知道为什么?
DECLARE DYNAMIC LIBRARY "kernel32"
FUNCTION CreateDirectoryA% (F$, X$)
FUNCTION GetLastError& ()
END DECLARE
F$ = "TEMPX" + CHR$(0) ' new directory to create
x = CreateDirectoryA(F$, CHR$(0))
IF x = 0 THEN
IF GetLastError = &H3E6 THEN
PRINT "Invalid access to memory location."
END IF
END IF
这段代码是用QB64写的。
此代码在发生异常 x3E6 时强制创建目录,但确实首先解释了错误发生的原因:
DECLARE DYNAMIC LIBRARY "kernel32"
FUNCTION CreateDirectoryA% (F$, X$)
FUNCTION GetLastError& ()
END DECLARE
DO
F$ = "TEMPX" + CHR$(0) ' new directory to create
x = CreateDirectoryA(F$, CHR$(0))
IF x THEN ' successful create
EXIT DO
END IF
IF x = 0 THEN
REM Test for Invalid access to memory location.
IF GetLastError = &H3E6 THEN
_DELAY .2
ELSE
EXIT DO
END IF
END IF
LOOP
您作为 CreateDirectoryA
的 lpSecurityAttributes
参数传递的是长度为 0 的字符串;字符串仍然有内存地址,这意味着你传递的是一个非空指针。这被 CreateDirectoryA 解释为指向 SECURITY_ATTRIBUTES structure 的指针,其第一个字节设置为 0。结构中的其余字节是您尚未初始化的内存,这意味着结构的第一个字段 nLength
一个小端机器可能类似于 0xFFFFFF00
,即 4294967040——一个无效的大小。该结构的 lpSecurityDescriptor
字段可能也填充了字节(您的程序可能可以访问,但也许不能访问),因此这也可能导致问题。
您可以轻松解决此问题:
' X%& may also be written X AS _OFFSET.
FUNCTION CreateDirectoryA% (F$, BYVAL X%&)
...
x = CreateDirectoryA(F$, 0)
这导致正确传递 NULL
指针。 BYVAL
关键字是必需的,否则您将传递一个指向 _OFFSET
值的指针(因为 QB64 中的所有内容都是通过指针传递的,除非您使用 BYVAL
关键字;字符串和用户-无法传递定义的类型 BYVAL
).
然后我 运行 在路径中创建子目录时遇到问题,所以我这样写:
DECLARE DYNAMIC LIBRARY "kernel32"
FUNCTION CreateDirectoryA% (F$, BYVAL X&&)
FUNCTION GetLastError& ()
END DECLARE
DO ' get directory
PRINT "Dir";: INPUT Directory$
IF Directory$ = "" THEN END
GOSUB CreateDir
LOOP
END
CreateDir:
' construct path
Directory$ = RTRIM$(Directory$)
IF RIGHT$(Directory$, 1) <> "\" THEN
Directory$ = Directory$ + "\"
END IF
' create path
x = 0
Next.Dir = INSTR(Directory$, "\")
DO
IF Next.Dir = False THEN
EXIT DO
END IF
SubDir$ = LEFT$(Directory$, Next.Dir - 1) ' \tempx\t1\t2\t3\
Next.Dir = INSTR(Next.Dir + 1, Directory$, "\")
' make directory name
IF LEN(SubDir$) THEN
' create directory
f$ = SubDir$ + CHR$(0)
x = CreateDirectoryA(f$, 0)
' check error
IF x = 0 THEN
IF GetLastError& = &HB7 THEN ' ignore already exists
' nul
ELSE
EXIT DO
END IF
END IF
END IF
LOOP
IF x = 0 THEN
PRINT "Error x"; HEX$(GetLastError&)
ELSE
PRINT "Directory created."
END IF
RETURN
这样,如果您指定一个不存在的路径,它将创建整个路径名。例如,如果 \Temp 不存在,\Temp\t1\t2\t3。
我有以下代码,有时 returns 在尝试创建新目录时出错。有时当该目录不存在时,它会抛出错误并且不会创建该目录。我想知道为什么?
DECLARE DYNAMIC LIBRARY "kernel32"
FUNCTION CreateDirectoryA% (F$, X$)
FUNCTION GetLastError& ()
END DECLARE
F$ = "TEMPX" + CHR$(0) ' new directory to create
x = CreateDirectoryA(F$, CHR$(0))
IF x = 0 THEN
IF GetLastError = &H3E6 THEN
PRINT "Invalid access to memory location."
END IF
END IF
这段代码是用QB64写的。
此代码在发生异常 x3E6 时强制创建目录,但确实首先解释了错误发生的原因:
DECLARE DYNAMIC LIBRARY "kernel32"
FUNCTION CreateDirectoryA% (F$, X$)
FUNCTION GetLastError& ()
END DECLARE
DO
F$ = "TEMPX" + CHR$(0) ' new directory to create
x = CreateDirectoryA(F$, CHR$(0))
IF x THEN ' successful create
EXIT DO
END IF
IF x = 0 THEN
REM Test for Invalid access to memory location.
IF GetLastError = &H3E6 THEN
_DELAY .2
ELSE
EXIT DO
END IF
END IF
LOOP
您作为 CreateDirectoryA
的 lpSecurityAttributes
参数传递的是长度为 0 的字符串;字符串仍然有内存地址,这意味着你传递的是一个非空指针。这被 CreateDirectoryA 解释为指向 SECURITY_ATTRIBUTES structure 的指针,其第一个字节设置为 0。结构中的其余字节是您尚未初始化的内存,这意味着结构的第一个字段 nLength
一个小端机器可能类似于 0xFFFFFF00
,即 4294967040——一个无效的大小。该结构的 lpSecurityDescriptor
字段可能也填充了字节(您的程序可能可以访问,但也许不能访问),因此这也可能导致问题。
您可以轻松解决此问题:
' X%& may also be written X AS _OFFSET.
FUNCTION CreateDirectoryA% (F$, BYVAL X%&)
...
x = CreateDirectoryA(F$, 0)
这导致正确传递 NULL
指针。 BYVAL
关键字是必需的,否则您将传递一个指向 _OFFSET
值的指针(因为 QB64 中的所有内容都是通过指针传递的,除非您使用 BYVAL
关键字;字符串和用户-无法传递定义的类型 BYVAL
).
然后我 运行 在路径中创建子目录时遇到问题,所以我这样写:
DECLARE DYNAMIC LIBRARY "kernel32"
FUNCTION CreateDirectoryA% (F$, BYVAL X&&)
FUNCTION GetLastError& ()
END DECLARE
DO ' get directory
PRINT "Dir";: INPUT Directory$
IF Directory$ = "" THEN END
GOSUB CreateDir
LOOP
END
CreateDir:
' construct path
Directory$ = RTRIM$(Directory$)
IF RIGHT$(Directory$, 1) <> "\" THEN
Directory$ = Directory$ + "\"
END IF
' create path
x = 0
Next.Dir = INSTR(Directory$, "\")
DO
IF Next.Dir = False THEN
EXIT DO
END IF
SubDir$ = LEFT$(Directory$, Next.Dir - 1) ' \tempx\t1\t2\t3\
Next.Dir = INSTR(Next.Dir + 1, Directory$, "\")
' make directory name
IF LEN(SubDir$) THEN
' create directory
f$ = SubDir$ + CHR$(0)
x = CreateDirectoryA(f$, 0)
' check error
IF x = 0 THEN
IF GetLastError& = &HB7 THEN ' ignore already exists
' nul
ELSE
EXIT DO
END IF
END IF
END IF
LOOP
IF x = 0 THEN
PRINT "Error x"; HEX$(GetLastError&)
ELSE
PRINT "Directory created."
END IF
RETURN
这样,如果您指定一个不存在的路径,它将创建整个路径名。例如,如果 \Temp 不存在,\Temp\t1\t2\t3。