vs2017 输出错误,但 mingw 有效

Posted

技术标签:

【中文标题】vs2017 输出错误,但 mingw 有效【英文标题】:wrong output by vs2017 but mingw works 【发布时间】:2017-06-22 07:03:48 【问题描述】:

我写了一个简单的函数来从文件中加载一个 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] = '\0';
    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)] = '\0';
    fclose(file);
    return buffer;

【问题讨论】:

这里有一条注释说ftell with files open in text mode 报告位置不正确:msdn.microsoft.com/en-us/library/0ys3hc0b.aspx 也许是对的,添加了一个可行的解决方案 这只是 vs 的 ftell 报告错误,我的意思是 gcc 的版本有效 【参考方案1】:

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

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

将文件位置指示器设置为文件结尾,与 fseek(file, 0, SEEK_END),对二进制文件有未定义的行为 流...

7.21.9.2 fseek 函数

...二进制流不需要有意义地支持fseek调用 whence 的值为SEEK_END

所以你不能可靠地使用fseek() 来到达二进制文件的末尾。事实上,C 标准明确将这样做定义为未定义的行为。

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

7.21.9.4 ftell 函数

...

对于文本流,其文件位置指示符包含未指定 信息,可由fseek 函数用于返回文件 流的位置指示器到其当时的位置 ftell 通话;两个这样的回报之间的差异 值不一定是对数量的有意义的度量 写入或读取的字符。

在文本文件中,ftell() 不会返回对获取文件大小有用的值。

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

【讨论】:

它是否可能会在某个时候报告得更少或者它过于执行细节?因为那样我使用的解决方案就会中断。 @bluedragon C 没有标准化的“文件”概念,因此任何解决方案都必须是特定于平台的。对于Windows,我认为GetFileSize( fileno( file ) ); 应该可以工作,尽管GetFileSizeEx() 可能更好,而struct stat sb; fstat( fileno( file ) &amp;sb ); 可以在POSIX 系统上工作。在 Windows 和 POSIX 系统上,binary 流上的 fseek()/ftell() 确实有效,但大小限制为签名的 long 值,或在 Windows 上为 2 GB。您可以使用ftello() 获取off_t 值,对于 64 位所有架构,该值应为 64 位。 寻找 EOF 的循环是否适用于正确的 ftell()

以上是关于vs2017 输出错误,但 mingw 有效的主要内容,如果未能解决你的问题,请参考以下文章

解析器错误消息:文件“/TestSite/Default.aspx.cs”不存在

html vs2.html

typescript vs2.ts

就绪/有效 vs 2 次握手 vs 4 次握手

为什么Qt的libstdc ++版本 - 6.dll有效,但不是MinGW?

VS2017中使用ObjectARX 2019 wizard的 ArxWizMFCSupport向导出现的bug修复前因后果