与`g++有关wexitstatus的奇怪行为4.9.4`

发布于 2025-02-01 10:57:09 字数 2055 浏览 4 评论 0 原文

下面的此代码段确实编译了,

#include<sys/types.h>
#include<sys/wait.h>
#include<iostream>

int main()
{
    int ret = 0xFFFF;
    std::cout << WEXITSTATUS(ret);
}

而此代码段的确没有使用 g ++ 4.9.4

#include<sys/types.h>
#include<sys/wait.h>
#include<iostream>

int main()
{
     std::cout << WEXITSTATUS(0xFFFF);
}

这是编译器抱怨的内容:

In file included from /usr/include/x86_64-linux-gnu/sys/wait.h:77:0,
                 from t.cpp:2:
t.cpp: In function ‘int main()’:
t.cpp:7:22: error: lvalue required as unary ‘&’ operand
         std::cout << WEXITSTATUS(0xFFFF);
                      ^

这是有关编译器的详细信息:

g++ --version
g++ (Ubuntu 4.9.4-2ubuntu1~16.04) 4.9.4
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

编译 器的详细信息: ubuntu16.04通过以下命令

sudo apt-get install gcc-4.9
sudo apt-get install g++-4.9
sudo update-alterntives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 20
sudo update-alterntives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 20

注: 我必须使用G ++ -4.9,我别无选择。

奇怪的是,我无法在 godbolt.org 上重现上述现象。它在godbolt.org上编译带有 gcc 4.9.3.3 ) GCC 4.9.4 不可用)。

这是 g ++ -e -e the_said_code_snippet_does_not_compile.cpp 的输出

//omit
# 4 "t.cpp" 2

int main()
{
        std::cout << ((((*(const int *) &(0xFFFF))) & 0xff00) >> 8);
}

更新

我现在可以重现错误!请参阅此链接

更新

这只是一个简化的示例。我实际上面对的是 wexitstatus(pclose(fp))没有编译。

This code snippet below does compiles,

#include<sys/types.h>
#include<sys/wait.h>
#include<iostream>

int main()
{
    int ret = 0xFFFF;
    std::cout << WEXITSTATUS(ret);
}

whereas this code snippet does not compile indeed with G++ 4.9.4:

#include<sys/types.h>
#include<sys/wait.h>
#include<iostream>

int main()
{
     std::cout << WEXITSTATUS(0xFFFF);
}

Here is what the compiler complains:

In file included from /usr/include/x86_64-linux-gnu/sys/wait.h:77:0,
                 from t.cpp:2:
t.cpp: In function ‘int main()’:
t.cpp:7:22: error: lvalue required as unary ‘&’ operand
         std::cout << WEXITSTATUS(0xFFFF);
                      ^

Here is the detail info about the compiler:

g++ --version
g++ (Ubuntu 4.9.4-2ubuntu1~16.04) 4.9.4
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

And the compiler is installed on Ubuntu16.04 by the commands below

sudo apt-get install gcc-4.9
sudo apt-get install g++-4.9
sudo update-alterntives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 20
sudo update-alterntives --install /usr/bin/g++ g++ /usr/bin/g++-4.9 20

Note:
I have to use g++-4.9, I have no other choice.

And It's strange that I could not reproduce the said phenomenon on godbolt.org. It compiles on godbolt.org with gcc 4.9.3(gcc 4.9.4 is not available).

Here is the output of g++ -E the_said_code_snippet_does_not_compile.cpp

//omit
# 4 "t.cpp" 2

int main()
{
        std::cout << ((((*(const int *) &(0xFFFF))) & 0xff00) >> 8);
}

Could anybody shed some light on this matter?

UPDATED:

I can reproduce the error now!See this link.

UPDATED:

It's just a simplified example. What am I actually face is WEXITSTATUS(pclose(fp)) does not compile.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

看轻我的陪伴 2025-02-08 10:57:09

wexitstatus 宏是C标准库实现的问题,而不是编译器本身。通常(对于GCC),编译器不提供C标准库实施。这是一个独立的软件包。

包括Ubuntu在内的大多数Linux发行版都使用GLIBC作为C标准库实现。

在GLIBC直到版本2.23(包含)中,使用C ++和 __ USE_MISC 已设置(请参见下面的提示链接):

#   define __WAIT_INT(status)   (*(const int *) &(status))

// ...

# define WEXITSTATUS(status)    __WEXITSTATUS (__WAIT_INT (status))

宏的实际实现在 __ wexitstatus 中,但是使用 wait_int 似乎是为了支持 Wait 接口的非posix“ Union Wait ”变体。通过此定义,宏无法使用prvalue,因为它试图获取 status 的地址。

在2016年,带有支持< em>联合等待 - 根据 News 在1990年代初提出的输入 - 已被删除,现在的定义也很简单

# define WEXITSTATUS(status)    __WEXITSTATUS (status)

,它也将与Prvalue一起使用。

似乎Ubuntu 16.04在更改之前仍使用GLIBC版本,这并不奇怪,因为它在提交时发布。

我不知道Posix对是否应该使用 int rvalue而不是变量的名称使用宏。

WexitStatus 不能总是直接在对 pclose 的调用上使用。显然,上述扩展现在不再存在于glibc中了,它也存在于(某些?)BSD中(并且可能源自它们?)。参见例如这个问题,答案还表示对Posix-Compliance的怀疑。但是,链接的问题中提到的OpenBSD也在2014年删除了 Union等待。 Noreferrer“> ChangElog 自4.3BSD(1986年发行)以来,它已被弃用。

The WEXITSTATUS macro is a matter of the C standard library implementation, not the compiler per se. Typically (and in the case of GCC) the compiler doesn't supply the C standard library implementation. It is an independent package.

Most Linux distributions, including Ubuntu, use glibc as C standard library implementation.

In glibc until version 2.23, inclusive, the macro was defined in the following way when using C++ and __USE_MISC is set (see commit link below):

#   define __WAIT_INT(status)   (*(const int *) &(status))

// ...

# define WEXITSTATUS(status)    __WEXITSTATUS (__WAIT_INT (status))

The actual implementation of the macro is inside __WEXITSTATUS, but the use of __WAIT_INT seems to be for the purpose of supporting the non-POSIX "union wait" variant of the wait interface. With this definition, a prvalue cannot be used with the macro, because it tries to take the address of status.

In 2016, with commit b49ab5f4503f36dcbf43f821f817da66b2931fe6 support for union wait - according to the NEWS entry deprecated in the early 1990s - has been removed and now the definition is simply

# define WEXITSTATUS(status)    __WEXITSTATUS (status)

Now it would work with a prvalue as well.

It seems that Ubuntu 16.04 still uses a glibc version from before that change, which isn't surprising since it was released at the time of the commit.

I don't know what POSIX has to say about whether or not it should be possible to use the macro with a int rvalue rather than the name of a variable.

That WEXITSTATUS can't always be used directly on a call to pclose seems to be known issue. Apparently the above-mentioned extension, which is now not present in glibc anymore, was (is?) also present in (some?) BSDs (and may originate from them?). See e.g. this question, in which the answer also expresses doubts about POSIX-compliance. However, OpenBSD, mentioned in the linked question, also removed union wait in 2014. According to the changelog it had been deprecated since 4.3BSD (released 1986).

妄断弥空 2025-02-08 10:57:09

这看起来像是宏观的奇数实现,导致了操作员优先级的问题。通常情况下应该是这样的:

#define     WEXITSTATUS(status)        (((status) & 0xff00) >> 8)

现在,如果它是(结果是完全错误的),

#define     WEXITSTATUS(status)        status & 0xff00 >> 8

您会遵循顺序:

( std::cout << status ) & (0xff00 >> 8)

尽管我无法想象存在这种破裂的实施可能存在吗?

处理的代码片段表明,宏假设状态是返回至少一个prvalue的表达式,人们可以将其施放到 const int 的“魔术”中。

#define     WEXITSTATUS(status)        ((((*(const int *) &(status))) & 0xff00) >> 8)

地址运营商遇到错误的操作数发生了错误。本质上,假设这些是从文档中描述的特定来源返回的值,则该宏不能仅与表达式或变量一起使用常数。

That looks like an oddball implementation of macro, causing problems with operator precedence. Usually it should be something like this:

#define     WEXITSTATUS(status)        (((status) & 0xff00) >> 8)

now if it is (and completely wrong as result)

#define     WEXITSTATUS(status)        status & 0xff00 >> 8

You wold get following order:

( std::cout << status ) & (0xff00 >> 8)

Though I can't imagine that such broken implementation could exist?

The processed code snippet shows that macro assumes status to be an expression returning at least a prvalue, something one can get address of and "magic" of casting it to const int.

#define     WEXITSTATUS(status)        ((((*(const int *) &(status))) & 0xff00) >> 8)

The error happens from address operator getting a wrong operand. Essentially this macro cannot work with a constant only with expression or variable, assuming that those are values returned from particular source described in documentation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文