【问题标题】:printf not printing to consoleprintf 不打印到控制台
【发布时间】:2024-01-16 02:51:02
【问题描述】:

使用 VS 2019 创建 C 程序以在 Windows 子系统 Linux (Ubuntu) 中运行。 使用 gcc starfire.c 作为程序的最初目的进行编译是为了其他目的,但已经演变成这种混乱。

void main() {
    printf("print this");
    return;
}

我尝试过使用fflush(stdout)setbuf(stdout, NULL),但两者都不起作用。请帮忙?

编辑:我也尝试过使用\n,所以也不是这样。我也在使用#include <stdio.h>,但它仍然无法正常工作。

【问题讨论】:

  • 试试这个程序:#include <stdio.h>int main(void) { printf("print this\n"); }
  • 也最好澄清你的前两句话:你是否使用 WSL GCC 作为 VS2019 中的自定义构建工具?
  • 如果你在 VS2019 中编辑,保存的文件很可能是 UTF-16 和 gcc 可能不喜欢的字节顺序标记。打开 VS Developers 命令提示符,切换到包含您的文件的目录并(在添加所需的头文件后)使用 gcc -Wall -Wextra -pedantic -O3 -o exenameyouwant nameoffile.c 编译(在编译没有警告之前不要接受代码)然后运行 ​​@987654330 @.
  • @DavidC.Rankin 如果 .c 是使用 UTF-16 生成的,那么 linux gcc 可能甚至无法编译它(语法错误)。由于 OP 已经尝试了 printf 的变体 [并且没有报告编译器错误],它似乎更像是一个运行时问题
  • 所以VS2019其实和问题无关,你是在WSL shell下使用gcc来构建和运行的?

标签: c printf windows-subsystem-for-linux


【解决方案1】:

x86 64 位调用约定对于 windows 和 linux不同

请参阅:https://en.wikipedia.org/wiki/X86_calling_conventions 特别是“Microsoft x64 调用约定”和“System V AMD64 ABI”部分。

在 Windows 中,前 四个 参数在寄存器中传递。但是,在 linux 下,前 六个 参数在寄存器中传递。

并且,哪个寄存器保存哪个参数[再次]不同:

            arg0    arg1    arg2    arg3    arg4    arg5
Windows:    RCX     RDX     R8      R9
Linux:      RDI     RSI     RDX     RCX     R8      R9

另外,哪些寄存器必须由被调用者保存,哪些可能会被丢弃等等,都是不同的。

在 Windows 下使用 gcccygwinmingw)将使用 MS 约定。在 WSL 下使用 gcc 将使用 ubuntu/linux SysV ABI(即 linux)约定。

所以,如果没有选项告诉编译器使用正确的调用约定,就不能只进行交叉编译。此外,动态库可能存在问题(在 MS 下它们是 .dll,但在 linux 下它们是 .so)。

此外,Windows 使用PE(可移植可执行文件)格式[源自 SysV COFF 格式]。但是,linux使用ELF对象/二进制可执行格式。

旁注: IIRC,MS 刚刚决定在 linux 下支持 VS [但那是最近的事],所以你可能会在那里得到一些缓解。

但是,IMO,我只会使用 gcc 等。人。在 WSL/ubuntu/linux 下。而且,如果你真的需要一个 IDE,试试 Eclipse。

您可以尝试让 VS 交叉构建,但是,IMO,墙上的标志是:放弃希望所有进入这里的人


更新:

警告:我根据 OP 的原始帖子发布了上述内容 [没有一些* cmets 的好处(关于 gcc 的使用方式)]。但是,我想得越多,这一切就越没有意义。

但是,这引出了一个问题:您使用的是WSL 还是WSL2?它们的实现方式不同。

使用WSL,MS 刚刚为 win10 内核添加了额外的 linux 兼容系统调用接口支持。它可以执行有限数量的程序。 AFAIK,这些程序仍然使用本机 NTFS 文件系统。您没有运行 linux 内核,只是执行一些 linux ABI 兼容的可执行文件。

借助WSL2,MS 实现了一个轻量级虚拟机[类似于vmwarevirtualbox],它允许完整的ubuntu/linux 内核运行。有了这个,您可以通过从“实时”ubuntu 安装.iso(直接来自 ubuntu 网站)引导 VM 来安装 ubuntu。然后它会安装 [几乎] 就像原生 ubuntu 安装一样。

因为WSL2是VM,所以可以类似的方式安装fedorasusemint等。

【讨论】:

  • 这很好。我没有考虑过试图在 Windows 中编译并在 WSL 中运行的 OP(反之亦然)。我还没有安装 VS2019,但我知道他们已经改进了与 WSL 的交互方式。在没有通过/mnt/c 复制以确保该文件是使用 Linux 文件权限信息创建的(否则该文件将在 WSL 中简单地消失)之前,您无法在 Windows 中进行编辑并在 WSL 中提供该文件。希望OP能提供澄清。
  • 据我所知,我使用的是WSL,而不是WSL2。链接here 上的任何内容都是我下载的。我最终使用的是一些在线 C 编译器,因为能够将代码作为程序运行(在我的机器上)并不是非常重要。我只是想看看我正在创建的代码的输出,并确保我的编码逻辑是正确的。