vs2017 输出错误但 mingw 有效

wrong output by vs2017 but mingw works

我写了一个简单的函数来从文件加载 char * 缓冲区,但是当通过 vs2017 编译时,它在缓冲区的末尾添加了垃圾,但是 mingw 编译的 exe 给出了正确的输出 该功能看起来像

#include <stdio.h>
#include <stdlib.h>

using namespace std;

char * loadfromfile(const char * _Filename)
{
    char * buffer;
    FILE * file = fopen(_Filename, "r");
    if (!file)
        return nullptr;
    fseek(file, 0, SEEK_END);
    auto _length = ftell(file);
    buffer = new char[_length + 1];
    rewind(file);
    printf("characters read(loadformfile()) :%i\n",fread(buffer, sizeof(char), _length, file));
    buffer[_length] = '[=10=]';
    fclose(file);
    return buffer;
}

int main() {
    char * str = loadfromfile("D:\shutdown.bat");
    printf("%s\n", (str) ? str : "failed to load");
    delete[] str;
    return 0;
}

VS2017 输出:

characters read(loadformfile()) :86
@echo off
Set minutes=30
set /a seconds=%minutes%*60
TIMEOUT /T %seconds%
shutdown /s
\inst 

g++(x86_64-posix-seh-rev0,由 MinGW-W64 项目构建)7.1.0 输出:

characters read(loadformfile()) :zu
@echo off
Set minutes=30
set /a seconds=%minutes%*60
TIMEOUT /T %seconds%
shutdown /s

文件是:

@echo off
Set minutes=30
set /a seconds=%minutes%*60
TIMEOUT /T %seconds%
shutdown /s

编辑:

A working solution 
char * loadfromfile(const char * _Filename)
{
    char * buffer;
    FILE * file = fopen(_Filename, "r");
    if (!file)
        return nullptr;
    fseek(file, 0, SEEK_END);
    auto _length = ftell(file);
    buffer = new char[_length + 1];
    rewind(file);
    buffer[fread(buffer, sizeof(char), _length, file)] = '[=14=]';
    fclose(file);
    return buffer;
}

您不能便携地使用 fseek()/ftell() 来获取文件的大小。

根据 the C Standard,脚注 268,第 301 页:

Setting the file position indicator to end-of-file, as with fseek(file, 0, SEEK_END), has undefined behavior for a binary stream ...

7.21.9.2 The fseek function

... A binary stream need not meaningfully support fseek calls with a whence value of SEEK_END.

所以您不能可靠地使用 fseek() 到达二进制文件的末尾。实际上,C 标准特别 声明这样做是未定义的行为。

好的,所以您可以使用 fseek() 到达以 text 模式打开的文件的末尾,但是

7.21.9.4 The ftell function

...

For a text stream, its file position indicator contains unspecified information, usable by the fseek function for returning the file position indicator for the stream to its position at the time of the ftell call; the difference between two such return values is not necessarily a meaningful measure of the number of characters written or read.

在文本文件上,ftell() 没有 return 一个对获取文件大小有用的值。

简而言之,使用fseek()/ftell()来获取文件的大小从根本上是错误的。它 有时 起作用的事实只是一个实现细节。