通过无效指针访问静态成员:保证“工作”? [英] Accessing static member through invalid pointer: guaranteed to "work"?

查看:111
本文介绍了通过无效指针访问静态成员:保证“工作”?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

设置

给定此用户定义的类型:

Given this user-defined type:

struct T
{
    static int x;
    int y;

    T() : y(38);
};

和必要的定义放在某处有用:

and the requisite definition placed somewhere useful:

int T::x = 42;

以下是流式传输 int 的值到 stdout

the following is the canonical way to stream the int's value to stdout:

std::cout << T::x;

控制

同时,由于 T 的实例不存在,以下(当然)无效:

Meanwhile, the following is (of course) invalid due to an instance of T not existing:

T* ptr = NULL; // same if left uninitialised
std::cout << ptr->y;

问题



Now consider the horrid and evil and bad following code:

T* ptr = NULL;
std::cout << ptr->x; // remember, x is static

引用 ptr 无效,如上所述。即使在这里没有发生物理存储器引用,我仍然相信它仍然算作一个,使上述代码UB。或者...是吗?

Dereferencing ptr is invalid, as stated above. Even though no physical memory dereference takes place here, I believe that it still counts as one, making the above code UB. Or... does it?

14882:2003 5.2.5 / 3明确说明 a-> b 转换为(*(a))。b ,并且:

14882:2003 5.2.5/3 states explicitly that a->b is converted to (*(a)).b, and that:


评估点或箭头前的后缀表达式;
即使结果不必要确定整个后缀表达式的值,也会发生此评估,例如,如果id-expression表示静态成员。

The postfix expression before the dot or arrow is evaluated; This evaluation happens even if the result is unnecessary to determine the value of the entire postfix expression, for example if the id-expression denotes a static member.

但是不清楚这里的评估是否涉及实际的引用。事实上,14882:2003和n3035都没有明确说明指针表达式在处理静态成员时是否必须求值为有效实例的指针。

But it's not clear whether "evaluation" here involves an actual dereference. In fact neither 14882:2003 nor n3035 seem to explicitly say either way whether the pointer-expression has to evaluate to a pointer to a valid instance when dealing with static members.

我的问题是,这是多么无效?它是真的特别禁止的标准(即使没有物理解引用),或者它只是一个奇怪的语言,我们可以逃避吗?

My question is, just how invalid is this? Is it really specifically prohibited by the standard (even though there's no physical dereference), or is it just a quirk of the language that we can probably get away with? And even if it is prohibited, to what extent might we expect GCC/MSVC/Clang to treat it safely anyway?

我的g ++ 4.4似乎产生的代码永远不会尝试

My g++ 4.4 appeared to produce code that never attempts to push the [invalid] this pointer onto the stack, with optimisations turned off.

BTW

BTW If T were polymorphic then that would not affect this, as static members cannot be virtual.

推荐答案


不清楚这里的评估是否涉及实际的引用。

it's not clear whether "evaluation" here involves an actual dereference.

我在这里读取评估为评估子表达式。这意味着将对一元 * 进行求值,并通过空指针执行间接操作,产生未定义的行为。

I read "evaluation" here as "the subexpression is evaluated." That would mean that the unary * is evaluated and you perform indirection via a null pointer, yielding undefined behavior.

这个问题(通过空指针访问静态成员)在另一个问题中讨论,什么时候调用null实例上的成员函数导致未定义的行为?虽然它具体讨论成员函数,我没有看到任何理由,数据成员在这方面有任何不同。

This issue (accessing a static member via a null pointer) is discussed in another question, When does invoking a member function on a null instance result in undefined behavior? While it discusses member functions specifically, I don't see any reason that data members are any different in this respect. There is some good discussion of the issue there.

有一个缺陷报告对C ++标准,询问调用静态成员函数通过空指针未定义? (请参见 CWG缺陷315 )此缺陷已关闭,其分辨率状态通过空指针调用静态成员函数是有效的:

There was a defect reported against the C++ Standard that asks "Is call of static member function through null pointer undefined?" (see CWG Defect 315) This defect is closed and its resolution states that it is valid to call a static member function via a null pointer:


p-> f 根据5.2.5 [expr.ref]重写为(* p).f() p 为空时不会出错,除非将左值转换为右值

p->f() is rewritten as (*p).f() according to 5.2.5 [expr.ref]. *p is not an error when p is null unless the lvalue is converted to an rvalue

但是,这个决议实际上是错误的。

However, this resolution is in fact wrong.

它假设空左值的概念,它是另一个缺陷的建议解决方案的一部分, CWG缺陷232 ,它询问更一般的问题通过空指针未定义行为间接?

It presupposes the concept of an "empty lvalue," which is part of the proposed resolution for another defect, CWG defect 232, which asks the more general question, "Is indirection through a null pointer undefined behavior?"

该缺陷的解决方案将使某些形式的间接指向空指针(如调用静态成员函数)有效。但是,该缺陷仍然存在,其分辨率尚未被纳入C ++标准。直到该缺陷被关闭并且其分辨率被并入到C ++标准中,通过空指针的间接(或取消引用空指针,如果更喜欢该术语)总是产生未定义的行为。

The resolution to that defect would make certain forms of indirection through a null pointer (like calling a static member function) valid. However, that defect is still open and its resolution has not been adopted into the C++ Standard. Until that defect is closed and its resolution is incorporated into the C++ Standard, indirection via a null pointer (or dereferencing a null pointer, if one prefers that term) always yields undefined behavior.

这篇关于通过无效指针访问静态成员:保证“工作”?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆