越界废话 [英] Out-of-bounds nonsense

查看:62
本文介绍了越界废话的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



[这篇文章涉及C和C ++,但不会疏远

语言,因为正在讨论的语言功能对于两者来说都很常见

语言。 ]


在comp.lang.c上,我们一直在讨论通过下标索引访问数组元素

,这些索引可能看起来不合适范围。特别是,

访问类似于以下内容:


int arr [2] [2];


arr [0] [3] = 7;


C标准和C ++标准都要求四个int'是
lain out in内存按升序排列,中间没有填充,即:


(最好以单字体字体查看)


------ --------------------------

|内存地址|对象|

--------------------------------

| 0 | arr [0] [0] |

| 1 | arr [0] [1] |

| 2 | arr [1] [0] |

| 3 | arr [1] [1] |

--------------------------------


我可以清楚地看到上面的小片段

应该没有问题,因为arr [0] [3]应该与arr [1]相同[1],但我已经在comp.lang.c上结了

人告诉我该片段的行为是因为out而未定义的
界限阵列访问。他们甚至支持

来自C标准的引用:


J.2未定义的行为:

在以下情况下,行为未定义:

[...]

- 数组下标超出范围,即使某个对象显然是

可以使用给定的下标访问(如左值表达式

a [1] [7]给出声明int [4] [5])(6.5.6)。


是否有人对C ++中存在的未定义行为提出同样的要求?


如果声称代码片段的行为未定义,因为

第二个下标索引超出了维度的范围,那么这个

的理由可能会因以下细分而受到质疑。首先让's

看表达式声明:


arr [0] [3] = 9;


C和C ++中的编译器必须将其解释为:


*(*(arr + 0)+ 3)= 9;


在最内部括号中,arr衰减指向其第一个元素的指针,即int(*)[2]类型的R值。然后将值0添加到此地址

,这无效。然后取消引用地址

,得到int [2]类型的L值。然后这个表达式

衰减到指向其第一个元素的指针,产生一个类型为

int *的R值。然后将值3添加到该地址。 (就字节而言,它是p $ / b $ b + = 3 * sizeof(int))。然后取消引用该地址,产生int类型的L值

。然后将L值int分配给。


在上一段中听起来有点狡猾的唯一一点是

L值type int [2]用作访问元素的垫脚石

,其索引大于1 - 但这不应该是一个问题,因为

在访问int对象的

之前,L值会衰减为一个简单的R值int指针,因此任何维度信息都应该丢失。


给C ++程序员:片段是否被视为调用未定义的

行为?如果是这样,为什么?


给C程序员:你怎么能理解这个断言呢?
实际上会调用未定义的行为?


我想提醒两个阵营,在其他地方,我们可以自由使用我们的

内存但是我们请它(因为它适当地对齐) , 当然)。对于

实例,请查看以下内容。代码是一个绝对的狗的晚餐,但

它应该适用于所有实现:


/ *假设包含所有必要的标题* /


void输出(int); / *在别处定义* /


int main(无效)

{

断言(sizeof(double)sizeof(int) );


{/ *开始* /


double * p;

int * q;

char unsigned const * pover;

char unsigned const * ptr;


p = malloc(5 * sizeof * p);

q =(int *)p ++;

pover =(char unsigned *)(p + 4);

ptr =(char unsigned *)p ;

p [3] = 2423.234;

* q ++ = -9;

do输出(* ptr ++);

while(pover!= ptr);


返回0;


} / *结束* /

}


我要提醒两个阵营的另一件事是,我们可以访问任何内存,就好像它只是一个无符号字符数组''秒。这意味着我们可以

访问int [2] [2]好像它只是一个类型为char

unsigned [sizeof(int [2] [2])]的对象。


我写这个的原因是,此刻,它听起来像是绝对的,我原来的片段的行为是未定义的,所以我

挑战那些支持其所谓的不确定性的人。


我告诉你:


int arr [2] [2];


void * const pv =& arr;


int * const pi =(int *)pv; / * Cast用于C ++程序员! * /


pi [3] = 8;


-


Frederick Gotham

解决方案

Frederick Gotham< fg ******* @ SPAM.com撰写:


[这篇文章涉及C和C ++,但不会疏远

语言,因为讨论的语言特性对于两种语言都是通用的。 ]


在comp.lang.c上,我们一直在讨论通过下标索引访问数组元素

,这些索引可能看起来不合适范围。



[snip]


这是多次发布到至少两个新闻组,comp.std.c和

comp.lang.c. (鉴于内容,它可能已被发布到一个或多个b
更多的C ++新闻组,但我还没有检查过。)


我提到这样,读者在决定是否以及在何处发布后续行动时会意识到这一点。


-

Keith汤普森(The_Other_Keith) ks***@mib.org < http://www.ghoti.net/~kst>

圣地亚哥超级计算机中心< *< http://users.sdsc.edu/~kst>

我们必须做点什么。这是事情。因此,我们必须这样做。


Keith Thompson:


这是多次发布到至少两个新闻组,comp.std.c和

comp.lang.c. (鉴于内容,它可能已被发布到一个或多个b
更多的C ++新闻组,但我还没有检查过。)


我提到这样,读者在决定是否以及在何处发布后续行动时会意识到这一点。



我不确定它比交叉发布更有利,虽然我知道

我自己的新闻阅读器弄得一团糟交叉帖子(...更不用说我不知道​​他们应该如何工作)。


我确实发布到C新闻组和C ++新闻组。


-


Frederick Gotham


< blockquote> Frederick Gotham写道:


[...]但是我已经在comp.lang.c上告诉了人们
我认为该片段的行为是由于越界而未定义的。阵列访问。他们甚至支持

来自C标准的报价:

[...]



弗雷德里克,你没有义务相信。但是如果你选择不相信,那么你可以悄悄地离开圣殿。你喜欢的任何一扇门,只要停下来就可以了。
mewling。请?


这个男人说服了他的遗嘱

仍有相同的意见。


-

Eric Sosman
es ***** @ acm-dot -org.inva



[ This post deals with both C and C++, but does not alienate either
language because the language feature being discussed is common to both
languages. ]

Over on comp.lang.c, we''ve been discussing the accessing of array elements
via subscript indices which may appear to be out of range. In particular,
accesses similar to the following:

int arr[2][2];

arr[0][3] = 7;

Both the C Standard and the C++ Standard necessitate that the four int''s be
lain out in memory in ascending order with no padding in between, i.e.:

(best viewed with a monowidth font)

--------------------------------
| Memory Address | Object |
--------------------------------
| 0 | arr[0][0] |
| 1 | arr[0][1] |
| 2 | arr[1][0] |
| 3 | arr[1][1] |
--------------------------------

One can see plainly that there should be no problem with the little snippet
above because arr[0][3] should be the same as arr[1][1], but I''ve had
people over on comp.lang.c telling me that the behaviour of the snippet is
undefined because of an "out of bounds" array access. They''ve even backed
this up with a quote from the C Standard:

J.2 Undefined behavior:
The behavior is undefined in the following circumstances:
[...]
- An array subscript is out of range, even if an object is apparently
accessible with the given subscript (as in the lvalue expression
a[1][7] given the declaration int a[4][5]) (6.5.6).

Are the same claims of undefined behaviour existing in C++ made by anyone?

If it is claimed that the snippet''s behaviour is undefined because the
second subscript index is out of range of the dimension, then this
rationale can be brought into doubt by the following breakdown. First let''s
look at the expression statement:

arr[0][3] = 9;

The compiler, both in C and in C++, must interpret this as:

*( *(arr+0) + 3 ) = 9;

In the inner-most set of parentheses, "arr" decays to a pointer to its
first element, i.e. an R-value of the type int(*)[2]. The value 0 is then
added to this address, which has no effect. The address is then
dereferenced, yielding an L-value of the type int[2]. This expression then
decays to a pointer to its first element, yielding an R-value of the type
int*. The value 3 is then added to this address. (In terms of bytes, it''s p
+= 3 * sizeof(int)). This address is then dereferenced, yielding an L-value
of the type int. The L-value int is then assigned to.

The only thing that sounds a little dodgy in the above paragraph is that an
L-value of the type int[2] is used as a stepping stone to access an element
whose index is greater than 1 -- but this shouldn''t be a problem, because
the L-value decays to a simple R-value int pointer prior to the accessing
of the int object, so any dimension info should be lost by then.

To the C++ programmers: Is the snippet viewed as invoking undefined
behaviour? If so, why?

To the C programmers: How can you rationalise the assertion that it
actually does invoke undefined behaviour?

I''d like to remind both camps that, in other places, we''re free to use our
memory however we please (given that it''s suitably aligned, of course). For
instance, look at the following. The code is an absolute dog''s dinner, but
it should work perfectly on all implementations:

/* Assume the inclusion of all necessary headers */

void Output(int); /* Defined elsewhere */

int main(void)
{
assert( sizeof(double) sizeof(int) );

{ /* Start */

double *p;
int *q;
char unsigned const *pover;
char unsigned const *ptr;

p = malloc(5 * sizeof*p);
q = (int*)p++;
pover = (char unsigned*)(p+4);
ptr = (char unsigned*)p;
p[3] = 2423.234;
*q++ = -9;
do Output(*ptr++);
while (pover != ptr);

return 0;

} /* End */
}

Another thing I would remind both camps of, is that we can access any
memory as if it were simply an array of unsigned char''s. That means we can
access an "int[2][2]" as if it were simply an object of the type "char
unsigned[sizeof(int[2][2])]".

The reason I''m writing this is that, at the moment, it sounds like absolute
nonsense to me that the original snippet''s behaviour is undefined, and so I
challenge those who support its alleged undefinedness.

I leave you with this:

int arr[2][2];

void *const pv = &arr;

int *const pi = (int*)pv; /* Cast used for C++ programmers! */

pi[3] = 8;

--

Frederick Gotham

解决方案

Frederick Gotham <fg*******@SPAM.comwrites:

[ This post deals with both C and C++, but does not alienate either
language because the language feature being discussed is common to both
languages. ]

Over on comp.lang.c, we''ve been discussing the accessing of array elements
via subscript indices which may appear to be out of range.

[snip]

This was multi-posted to at least two newsgroups, comp.std.c and
comp.lang.c. (Given the content, it may have been posted to one or
more C++ newsgroups as well, but I haven''t checked.)

I mention this so that readers will be aware of it when deciding
whether and where to post a followup.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.


Keith Thompson:

This was multi-posted to at least two newsgroups, comp.std.c and
comp.lang.c. (Given the content, it may have been posted to one or
more C++ newsgroups as well, but I haven''t checked.)

I mention this so that readers will be aware of it when deciding
whether and where to post a followup.


I wasn''t sure how preferable it was over cross-posting, although I know that
my own newsreader makes a mess of cross-posts (...not to mention I don''t
quite understand how they''re supposed to work).

I have indeed posted to both C newsgroups and C++ newsgroups.

--

Frederick Gotham


Frederick Gotham wrote:

[...] but I''ve had
people over on comp.lang.c telling me that the behaviour of the snippet is
undefined because of an "out of bounds" array access. They''ve even backed
this up with a quote from the C Standard:
[...]

Frederick, you are under no obligation to believe. But
if you choose to disbelieve, do the believers the courtesy of
leaving the temple quietly. Any door you like, just stop
the mewling. Please?

"The man convinced against his will
Is of the same opinion still."

--
Eric Sosman
es*****@acm-dot-org.invalid


这篇关于越界废话的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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