答案 0 :(得分:4)
我们遇到了一个非常类似的问题,我们很容易重现这个问题。我们首先编写了以下程序:
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{ int len = 70000000;
int handle= creat(argv[1], S_IWRITE | S_IREAD);
setmode (handle, _O_BINARY);
void *buf = malloc(len);
int byteswritten = write(handle, buf, len);
if (byteswritten == len)
printf("Write successful.\n");
else
printf("Write failed.\n");
close(handle);
return 0;
}
现在,假设您正在使用计算机mycomputer,并且C:\ inbox映射到共享文件夹\\ mycomputer \ inbox。然后观察以下效果:
C:\>a.exe C:\inbox\x
Write successful.
C:\>a.exe \\mycomputer\inbox\x
Write failed.
请注意,如果len更改为60000000,则没有问题......
基于此网页support.microsoft.com/kb/899149,我们认为这是“操作系统的限制”(与fwrite相同的效果)。我们的工作是尝试削减63 MB的写入,如果它失败。在Windows Vista上,此问题显然已得到纠正。
我希望这有帮助! 西蒙
答案 1 :(得分:1)
您是否看过使用Visual Studio(_write()
)安装的CRT(C运行时)源中C:\Program Files\Microsoft Visual Studio 8\VC\crt\src\write.c
的实现?
至少有两个条件导致_write()
将errno
设置为EINVAL
:
buffer
为NULL。count
参数是奇数。这是文本还是二进制文件?如果是文本,它是否有字节顺序标记?_write()
调用的另一个函数也会将errno
设置为EINVAL
?如果能够可靠地重现此问题,您应该能够通过在设置错误代码的CRT源部分中放置断点来缩小错误源。看来CRT的调试版本能够在发生错误时断言,但可能需要tweaking some options(我还没试过)。
答案 2 :(得分:1)
根据http://msdn.microsoft.com/en-us/library/1570wh78(v=VS.90).aspx errno可以取值:
- EBADF
- ENOSPC
- EINVAL.
Windows上没有EINTR。随机系统中断会导致此错误,并且不会被测试while (-1==nbytes && EINTR==errno);
答案 3 :(得分:0)
我想到了两个想法。要么你走过缓冲区的末尾,又试图写出那些数据,或者缓冲区的分配失败了。在调试模式下,问题不会像在发布模式下那样可见。
无论如何分配250兆内存可能是一个坏主意。你最好分配一个固定大小的缓冲区,并以块的形式进行写作。
您是否已经查找过类似病毒扫描程序的内容,这些内容可能会在您的写入操作之间保留文件,从而导致写入失败?
我知道你可以在一次调用中传递的数据量没有限制,除非(就像我说的那样),你正在编写不属于你的数据(作为缓冲区的一部分)...
由于大多数这些函数都包含内核调用WriteFile(),(或NtWriteFile()),因此可能存在没有足够的内核内存来处理要写入的缓冲区的条件。但是,我不确定,因为我不知道该代码何时从UM跳转到KM。
不知道这是否会有所帮助,但希望确实如此......
如果您可以提供更多详细信息,请执行。有时只是告诉别人这个问题会引发你的大脑“等一下!”,你就会明白这一点。 HEH ..
答案 4 :(得分:0)
你可能会因意外误用其他地方的指针而丢弃你自己的堆栈 - 如果你能找到一台repro机器,试着在Application Verifier下运行你的应用程序并启用所有内存检查