【问题标题】:fopen fails mysteriously under Windowsfopen 在 Windows 下神秘失败
【发布时间】:2010-07-18 16:39:17
【问题描述】:

也许我只是又一次停电了,但是,这一行给我带来了很多麻烦:

FILE *fp = fopen("data/world.data", "rb");

当使用 GCC 编译时,这在 Linux 下可以正常工作。但是当我用 Visual Studio 编译它时,它崩溃了。 fp 始终为NULL。 BIN 和 EXE 都在完全相同的目录中。现在,更疯狂的是,当我在 Linux 下使用 Wine 运行 EXE 时……它……可以工作……

我完全不知道这里发生了什么。也许这对我来说是一个非常愚蠢的错误,但我无法让这个东西在 Windows 下运行:/

另外,我还有一个运行良好的程序,数据文件也包含在一个名为 data 的子目录中。

编辑
说清楚/ NOR `\ * 都行不通。

编辑 2:
好的,我已经放弃了,也许有人想弄清楚它很有趣,这里是包含 EXE、VS 调试数据等的 ZIP:
https://dl.dropbox.com/u/2332843/Leaf.zip

编辑 3:
用 CodeBlocks 和 MinGW 编译它,就像一个魅力。猜猜它必须与 MSVC 或 VS 中的项目设置有关。

【问题讨论】:

  • 尝试将“data/world.data”更改为“data\\world.data”
  • 我应该把它作为答案发布... -_-
  • 你有没有忘记在项目配置属性中设置“工作目录”? Visual Studio 在调试/发布文件夹中创建 *.exes,并默认从那里运行(当您从 Visual Studio 启动应用程序时)它们。 IE。如果您的“数据”在其他地方,您的 exe 将无法找到它。您可以将“工作目录”设置为 $(ProjectDir) 或 $(SolutionDir) 之类的东西,这样会很方便。
  • 无论您在代码中做什么:fopen("data/world.data"); 都能完美运行,而且很可能不是崩溃的原因,恕我直言。

标签: c windows fopen


【解决方案1】:

听起来data 不是您运行程序时当前 目录的子目录。默认情况下(对于 x86 目标)VS 将从您为项目创建的基本目录的 DEBUG 或 RELEASE 子目录构建和运行您的程序。您可以修改运行时“当前”的目录(例如,项目 | 属性 | 配置属性 | VS 2008 的调试)。

编辑:虽然 Windows 要求您在命令行中使用反斜杠作为目录分隔符,但在代码中使用正斜杠很好 -- 这不是源你的问题。

【讨论】:

  • 我把程序和数据文件夹一起移到了几个不同的地方,在我的办公桌上移到了 Dropbox,在那里我可以在 Win 和 Linux 上运行它,它总是在 Win 上崩溃,但它运行在 Wine 下就好了。
  • @Ivo:您是否尝试过使用数据目录的绝对路径来确保无论可执行文件的位置如何都能找到它?
  • 我现在几乎已经尝试了所有方法,我移动了调用包含 fopen 调用的函数的代码,剥离了对 fopen 等的其他调用。只是对 fopen("data/world.data", "rb"); 的调用失败了,我有其他成功的。我想我只是想尝试用 Code::Blocks 编译它,Visual Studio 在我的上网本上实在是太慢了。是的,我已经在另一台 Windows 机器上试过了。
【解决方案2】:

在windows中你必须写以下内容:

FILE *fp = fopen("data\\world.data", "rb");

之所以这样,是因为反斜杠是一个特殊字符(因此字符串中的反斜杠使用 \ 编写,引号是 \" 以及其他特殊字符)。

【讨论】:

    【解决方案3】:

    由于此问题仅在 Windows 上发生。我怀疑该文件是否真的被命名为“world.data”。如您所知,Windows 的默认设置隐藏文件扩展名。它的真名是world.data.xxx吗?

    【讨论】:

      【解决方案4】:

      在 GetCurrentDirectory() 中添加一行,以查看您是否从预期的目录运行。

      当我在 Visual Studio 上使用 C#/C++ 进行开发时,我通常会从调试文件夹中运行它。我认为在 .net 中使用正斜杠代替反斜杠并不重要。

      【讨论】:

        【解决方案5】:

        我碰巧有同样的问题,突然我想通了。

        那应该是你的 Windows 故障。

        假设FILE *fp = fopen("data/world.data", "rb");在windows中,如果你隐藏扩展名,那么你可以看到文件data/world.data,但实际上它可能是/data/world.dat.txt或其他。

        所以请检查扩展。

        希望对你有帮助!

        【讨论】:

        • 这里有一个教训:始终禁用隐藏扩展。它不仅可以防止这种混淆,而且当你收到一封包含 hello.dat 的电子邮件时,它实际上是 hello.dat.exe,你不会不小心打开它:)
        • 鉴于问题和cmets中的其他线索,这次不是这个问题。不过,您是对的,MS 的 隐藏扩展 会导致悲伤,值得仔细检查。
        【解决方案6】:

        我今天遇到了这个问题,因为我在那个模式参数上使用了“br”而不是“rb”。

        底层的 fopen 抛出某种异常,它只会注册为崩溃。返回标准的 NULL 响应或设置相关的错误值并不麻烦。

        【讨论】:

          【解决方案7】:

          我不确定,但可能是因为您在路径中使用斜杠而不是(转义的)反斜杠?

          【讨论】:

          • 另一个程序也使用了/,我已经用\\ 试过了,没有区别只是又一次崩溃:/
          • win2000上可以用斜杠代替反斜杠,winxp也没问题。它们可能会在 win98 及以下版本中引起问题。不确定它是否已记录在案,或者是否在 vista 或更高版本上得到官方支持。
          • @SigTerm: 所有 版本的 Windows 都可以接受正斜杠 -- 而 MS-DOS 回到最初支持子目录的版本 (2.x) 确实如此也是。 (非常)少数早期版本的 MS-DOS 甚至允许您在命令行中将其设置为分别接受 '/' 和 '-' 代替 '\' 和 '/'(即遵循 UNIX 约定)。
          • @Jerry Coffin:我说“可能”,意思是我不确定。我说只是因为人们曾经报告过该程序(一直使用正斜杠)拒绝在win98上正常工作。由于我无法在那台机器上调试程序,我不知道路径分隔符是否导致了问题。此外,如果您确定它是受支持的行为,那么如果您提供一些来自 msdn 的链接,该行为已正式记录在该链接中,那就太好了。这将轻松结束所有争论。
          • @SigTerm:我根本不是想说你错了——只是说你可能已经意识到的更正确。 @akira 已经在对原始问题的评论中提供了 MSDN 链接。我怀疑在这么晚的日子里,我们会在 MSDN 上找到很多关于 Windows 98、95、2.11、MS-DOS 3.3 等旧版本的东西。