fwrite()向输出添加垃圾数据(WINE&Windows 7,mingw&MSVC;不是linux / gcc)

在某些情况下, fwrite写入额外的数据(比请求更多的字节)。 简短演示的输出是最简单的解释方式。 演示尝试创build两个2048字节的文件,并在每次fwrite调用后检查偏移量,以确定写入的字节数。 第一个fwrite调用写入两个额外的字节:

 len: 2048 current offset = 0 wrote 1024 bytes current offset = 1026 EXITING: offset % BLOCKSIZE = 2 len: 2048 current offset = 0 wrote 1024 bytes current offset = 1024 wrote 1024 bytes SUCCESS 

当编译为ELF(unix二进制文件)时,程序成功运行(写入2048字节到两个文件),但编译为PE(Windows二进制/可执行文件)时失败(如上所示)。 我试着编译和testing:

 Ubuntu 14.04 and gcc 4.8.2 - SUCCESS WINE 1.6.2 and mingw 4.8.2 - FAIL Windows 7 and mingw 4.8.2 - FAIL Windows 7 and Visual Studio 2013 - FAIL 

传递给fwrite的缓冲区中的实际数据会影响写入的额外字节数,但实际上每次都发生(除非您正在编写空字节)。

main.c中:

 #include <stdio.h> #include "stub.h" #include "stub2.h" size_t min(size_t a, size_t b) { return a<b?a:b; } #define BLOCKSIZE 1024 void test(char buf[], size_t len) { FILE *f = fopen("out", "w"); printf("len: %lu\n", len); for(size_t i=0;i<len;i+=BLOCKSIZE) { printf("current offset = %lu\n", ftell(f)); if(ftell(f) % BLOCKSIZE) { printf("EXITING:\noffset %% BLOCKSIZE = %d\n\n", ftell(f) % BLOCKSIZE); return; } size_t wrote = fwrite(buf + i, 1, min(len - i, BLOCKSIZE), f); printf("wrote %lu bytes\n", wrote); } printf("SUCCESS\n\n"); fclose(f); } int main() { test(stub_exe, stub_exe_len); test(stub2_exe, stub2_exe_len); return 0; } 

stub.hstub2.h是从/ dev / urandom的2048个字节和从/ dev / zero(分别)用xxd的2048个字节生成的。 例如:

 dd if=/dev/urandom of=stub2.exe bs=2048 count=1 xxd -i stub.exe stub.h dd if=/dev/zero of=stub2.exe bs=2048 count=1 xxd -i stub2.exe stub2.h 

免责声明:已经5天了,没有人发布“官方”的答案,所以我正在作出这个答复,接受它。 感谢ChristopheRetired Ninja ,回答这个问题。

简单的答案是,你需要以二进制模式打开二进制文件(通过添加一个' fopen的第二个参数)。

默认情况下, fopen以文本模式而不是二进制模式打开文件。 在文本模式下,写入文件时换行符( \n )被操作系统的换行符所取代,反之亦然。 与使用单个字符( \n )作为换行符的POSIX系统(Linux,OSX,BSD等)不同,Windows使用\r\n换行符序列。