C++ CFile::osNoBuffer标志在写入文件时导致异常

C++ CFile::osNoBuffer标志在写入文件时导致异常,c++,winapi,mfc,C++,Winapi,Mfc,(WINAPI创建文件-WINAPI写入文件) 当我使用winapi函数编写文件时,winapi中使用的标志(文件\标志\无\缓冲)工作正常 (WINAPI创建文件-CFile-write文件) 在这种情况下,也发生了错误,但这是因为CFile对象中缺少文件名,该对象是从winapi CreateFile函数接收的文件句柄创建的 (CFile创建文件-CFile-写入文件) 当我使用此标志(CFile::osNoBuffer)时,当我尝试向文件写入内容时会出现异常,告诉我发生了一些无法识别的错误

(WINAPI创建文件-WINAPI写入文件) 当我使用winapi函数编写文件时,winapi中使用的标志(文件\标志\无\缓冲)工作正常

(WINAPI创建文件-CFile-write文件) 在这种情况下,也发生了错误,但这是因为CFile对象中缺少文件名,该对象是从winapi CreateFile函数接收的文件句柄创建的

(CFile创建文件-CFile-写入文件) 当我使用此标志(CFile::osNoBuffer)时,当我尝试向文件写入内容时会出现异常,告诉我发生了一些无法识别的错误

可能出了什么问题

char chArr [] = "1234567890";
CFile file;
file.Open("c:\\mfc.txt",CFile::modeCreate| CFile::modeNoTruncate| CFile::modeWrite | CFile::osNoBuffer | CFile::osWriteThrough);
file.Write(chArr,sizeof(chArr)); // exception 
file.Flush(); 
file.Close();
请参阅MSDN上的讨论

使用标志
CFile::osNoBuffer
打开文件,或者将标志
file\u flag\u NO\u BUFFERING
传递给
CreateFile
,这是一种非常特殊的文件写入方式。它要求用于写入文件的所有缓冲区都与内存中的扇区边界对齐,并且只写入扇区大小的整数倍。除非您已采取特殊步骤来对齐正在传递的缓冲区(此处没有),并且还写入了至少512字节,否则它不太可能工作,除非设备自动忽略您的标志。我想您可能没有注意到,
WriteFile
返回了一个错误代码,而不是抛出异常

我想问:你为什么要指定这个标志?它的使用是非常专门的,如果您只是执行普通的日常文件I/O,比如编写文本文件,那么不应该指定此标志。它可能会减慢您的程序,并使其更加复杂。我还建议您删除
CFile::osWriteThrough

正如您所知:
FILE\u FLAG\u NO\u BUFFERING
的使用几乎完全是为了写入必须直接进入磁盘的大量数据,例如实时数据记录或视频录制应用程序
FILE\u FLAG\u WRITE\u to
用于诸如数据库日志文件之类的事情,为了确保事务正确性,每次写入之后都必须刷新这些文件。在其他情况下禁用这些缓存和缓冲通常会降低程序的速度

下面是一些有同样问题的人(尽管他们使用的是.NET,而不是C++)


编辑:感谢您提到Daryl的尺寸要求。

来自Doug在回答中提到的MSDN文件缓冲讨论

  • 文件访问大小,包括重叠结构中的可选文件偏移量(如果指定),必须为卷扇区大小的整数倍字节数。例如,如果扇区大小为512字节,则应用程序可以请求512、1024、1536或2048字节的读写,但不能请求335、981或7171字节的读写

  • 读写操作的文件访问缓冲区地址应该是扇区对齐的,这意味着在内存中的地址是卷扇区大小的整数倍时对齐。根据磁盘的不同,可能不会强制执行此要求

在我的系统上,改变

char chArr[] = "1234567890";


…消除了异常,但有一个明显的问题,我现在正在向文件写入一堆未初始化的垃圾字节。

如果安装了MFC源代码,则可以调试写入调用。可能有帮助。另外一点需要补充的是,读/写的大小必须是扇区大小的倍数(通常为512)。在本例中,写入大小仅为10字节。
char chArr[512] = "1234567890";