c - Win32 WriteFile 返回 0 字节作为写入的字节数。 lpBuffer 包含 4455 字节

标签 c windows debugging winapi

我有以下代码,它创建了两个文件。当调用最后 4455 字节的写入操作时,它返回 0 作为写入的字节数。这可能是由于顺序扫描的 dwFlagAttributes 且没有缓冲造成的吗?

hIn = CreateFile (fIn, GENERIC_READ, 0, NULL, OPEN_EXISTING, 
                    FILE_ATTRIBUTE_NORMAL | SSF | NBF, NULL);

Desired Access: Generic Read
Disposition:    Open
Options:    Sequential Access, No Buffering, Synchronous IO Non-Alert, Non-Directory File
Attributes: N
ShareMode:  None
AllocationSize: n/a
OpenResult: Opened

hOut = CreateFile (fOut, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
                    FILE_ATTRIBUTE_NORMAL | SSF | NBF, NULL);

Desired Access: Generic Write, Read Attributes
Disposition:    OverwriteIf
Options:    Sequential Access, No Buffering, Synchronous IO Non-Alert, Non-Directory File
Attributes: N
ShareMode:  None
AllocationSize: 0
OpenResult: Created     

创建文件后,有一个 while 循环读取 file1。然后将字节写入 file2。 file1 大约为 13MB。

while (ReadFile (hIn, aBuffer, BUF_SIZE, &nIn, NULL) && nIn > 0 && WriteOK) {
        for (iCopy = 0; iCopy < nIn; iCopy++)
            ccBuffer [iCopy] = (BYTE)((aBuffer [iCopy] + shift) % 256);
        WriteOK = WriteFile (hOut, ccBuffer, nIn, &nOut, NULL);
    }

从下面的反汇编中可以明显看出最后 4455 字节没有写入 file2。这可能是由于 CreateFile dwFlagAttributes 造成的吗?

0:000> kb
 # ChildEBP RetAddr  Args to Child
00 0018bd00 00411612 00000038 0018bdf8 00001167 kernel32!WriteFile
01 0018fe64 0041144c 00273a99 00273ac9 0000000a cci!cci_f+0x162
02 0018ff44 00411bbb 00000004 00273a78 002723e8 cci!main+0x6c
03 0018ff88 7698336a 7efde000 0018ffd4 77c29f72 cci!__tmainCRTStartup+0x122
04 0018ff94 77c29f72 7efde000 76d02536 00000000 kernel32!BaseThreadInitThunk+0xe
05 0018ffd4 77c29f45 00411122 7efde000 00000000 ntdll!__RtlUserThreadStart+0x70
06 0018ffec 00000000 00411122 7efde000 00000000 ntdll!_RtlUserThreadStart+0x1b

0:000> dd 0018bd00 la
0018bd00  0018fe64 00411612 00000038 0018bdf8
0018bd10  00001167 0018fe34 00000000 0018ff44
0018bd20  0018fe78 00000000

0:000> $number of bytes to be written 0x1167
0:000> .formats 00001167
Evaluate expression:
  Hex:     00001167
  Decimal: 4455
  Octal:   00000010547
  Binary:  00000000 00000000 00010001 01100111
  Chars:   ...g
  Time:    Wed Dec 31 20:14:15 1969
  Float:   low 6.24278e-042 high 0
  Double:  2.20106e-320

0:000> gu
eax=00000000 ebx=00000000 ecx=76b2df07 edx=00000057 esi=0018bd1c edi=0018fe64
eip=00411612 esp=0018bd1c ebp=0018fe64 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
cci!cci_f+0x162:
00411612 cmp     esi,esp

0:000> $number of bytes written
0:000> dd 0018fe34 l1
0018fe34  00000000

enter image description here

最佳答案

由于您正在编写非缓冲的内容,因此您需要遵守此处记录的对齐要求:https://msdn.microsoft.com/en-us/library/windows/desktop/cc644950.aspx

具体来说,文件访问必须以卷扇区大小的倍数开始,并且大小为卷扇区大小的倍数。您的 4455 大小的缓冲区不满足第二个要求。

当然,如果您只想写入最后的 4455 字节,那么您就会陷入困境。您需要将其四舍五入为卷扇区大小的倍数,并写入实际的 4455 字节,然后进行填充。将文件指针设置回那些 4455 字节的末尾,并调用 SetEndOfFile

关于c - Win32 WriteFile 返回 0 字节作为写入的字节数。 lpBuffer 包含 4455 字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39024579/

相关文章:

c - 程序在 setuid 和 setgid 之后仍然能够打开 root only 文件

c - 什么是 openwall crypt_r 的数据参数?

c# - 在调试期间,进入后台工作线程/线程。可能的?

c - 有没有很好的 Valgrind 替代 Windows?

php - 在代码中运行的 SQL 与 MySQL 命令行中运行的 SQL 有什么区别吗?

c++ - gcc 链接的默认库?

objective-c - Clang 静态分析器警告 "Null pointer argument in call to CFRelease"

windows - 无法使用来自 jenkins 的 git 从 tomcat 安装连接到 bitbucket

windows - HeapCreate 和 HeapAlloc 混淆

linux - 如何在 Windows 中设置 makefile