简体   繁体   English

动态分配的内存上的指针算法具有未定义的行为

[英]Undefined behavior with pointer arithmetic on dynamically allocated memory

I'm probably misunderstanding this, but does the c99 spec prevent any form of pointer arithmetic on dynamically allocated memory? 我可能对此有误解,但是c99规范会阻止动态分配内存上的任何形式的指针算术吗?

From 6.5.6p7... 从6.5.6p7 ...

For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type. 就这些运算符而言,指向不是数组元素的对象的指针的行为与指向长度为1且对象类型为其元素类型的数组的第一个元素的指针的行为相同。

... a pointer to an object not in an array is treated as if it points into an array of 1 item (when using the operators + and -). ...指向不在数组中的对象的指针将被视为指向1项数组(当使用运算符+和-时)。 Then in this snippet: 然后在此片段中:

char *make_array (void) {
    char *p = malloc(2*sizeof(*p));
    p[0] = 1; // valid
    p[1] = 2; // invalid ?
    return p;
}

...the second subscript p[1] is invalid? ...第二个下标p[1]无效? Since p points to an object not in an array it is treated as pointing to an object in an array of one item and then from 6.5.6p8... 由于p指向不在数组中的对象,因此将其视为指向由一项组成的对象,然后从6.5.6p8开始...

When an expression that has integer type is added to or subtracted from a pointer, the result has the type of the pointer operand. 将具有整数类型的表达式添加到指针或从指针中减去时,结果将具有指针操作数的类型。 If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integer expression. 如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向与原始元素偏移的元素,以使结果数组元素和原始数组元素的下标之差等于整数表达式。 In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i+n-th and i−n-th elements of the array object, provided they exist. 换句话说,如果表达式P指向数组对象的第i个元素,则表达式(P)+ N(相当于N +(P))和(P)-N(其中N的值为n)表示到数组对象的第i + n个元素和第i-n个元素(如果存在)。 Moreover, if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)-1 points to the last element of the array object. 此外,如果表达式P指向数组对象的最后一个元素,则表达式(P)+1指向数组对象的最后一个元素之后,如果表达式Q指向数组对象的最后一个元素之后,表达式(Q)-1指向数组对象的最后一个元素。 If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; 如果指针操作数和结果都指向同一数组对象的元素,或者指向数组对象的最后一个元素,则求值不会产生溢出; otherwise, the behavior is undefined. 否则,行为是不确定的。 If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated. 如果结果指向数组对象的最后一个元素之后,则不应将其用作被评估的一元*运算符的操作数。

...we have undefined behaviour since we dereference past the array bound (the one implied to have length 1). ...由于我们取消了对数组边界的引用(隐含长度为1),因此我们具有不确定的行为。

Edit: 编辑:

OK, to try to clarify more what confuses me, let's do it step-by-step: 好吧,要尝试弄清令我困惑的地方,让我们逐步进行:

1.) p[1] is defined to mean *(p+1) . 1.) p[1]被定义为均值*(p+1)
2.) p points to an object that isn't inside of an array, so it's treated as if it points to an object inside an array of length 1 for the purpose of evalutating p+1 . 2.) p指向不在数组内部的对象,因此为了评估p+1 ,将其视为指向长度为1的数组内部的对象。
3.) p+1 produces a pointer 1 past the array that p is implied to point into. 3.) p+1产生一个指针1,该指针越过暗示p指向的数组。
4.) *(p+1) does the invalid dereference. 4.) *(p+1)执行无效的取消引用。

From C99, 7.20.3 - Memory management functions (emphasis mine) : C99 7.20.3开始-内存管理功能 (强调我的功能 ):

The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated). 如果分配成功,则返回的指针将进行适当对齐,以便可以将其分配给指向任何类型对象的指针,然后将其用于访问已分配空间中的此类对象或此类对象的数组 (直到明确释放该空间) 。

This implies that the allocated memory can be accessed as an array of char (as per your example), and so pointer arithmetic is well defined. 这意味着可以将分配的内存作为char数组访问(按照您的示例),因此指针算术得到了很好的定义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM