Intel® C++ Compiler Classic Developer Guide and Reference

ID 767249
Date 12/16/2022
Public

A newer version of this document is available. Customers should click here to go to the newest version.

Document Table of Contents

How the Compiler Defines Bounds Information for Pointers

The pointer checker is not supported on macOS systems.

The following defines how the compiler determines the bound information for pointers.

NOTE:

In each section, lower_bound(p) refers to the lower bound associated with p and upper_bound(p) refers to the upper bound associated with p.

Pointers created by the alloca() function

p = alloca(size);
    // lower_bound (p) is (char *)p
    // upper_bound (p) is lower_bound(p) + size - 1

Pointers created by the calloc() function

p = calloc(num, size);
    // lower_bound(p) is (char *)p
    // upper_bound(p) is lower_bound(p) + size * num - 1

Pointers created by the malloc() function

p = malloc(size);
    // lower_bound(p) is (char *)p
    // upper_bound(p) is lower_bound(p) + size - 1

Pointers created by casting

p = (T *)q;
    // lower_bound(p) is lower_bound(q)
    // upper_bound(p) is upper_bound(q)

Casting a pointer does not affect the bounds of a pointer. If you cast a pointer to a new type that is larger than the bounds associated with the original pointer, you will get an out-of-bounds error when you try to access any member or element outside the original bounds. If you cast a pointer to a smaller type than the original pointer, you can still access the original data.

Pointers created for a variable length array in a structure

typedef struct {
	int num;
	int a[];
} T;

q = malloc(sizeof(T) + sizeof(int) * num);
p = &q->a;
    // lower_bound(p) is (char *)&q->a
    // upper_bound(p) is upper_bound(q)

When you define an array as the last member of a structure, the upper bound is not narrowed and is allowed to access all of the array elements allocated by the malloc() function.

Pointers defined by the address (&) operator

p = &v;
    // lower_bound(p) is (char *)&v
    // upper_bound(p) is (char *)&v + sizeof(v) - 1

p = &v.m;
    // lower_bound(p) is (char *)&v + offsetof(typeof(v),  m)
    // upper_bound(p) is lower_bound(p) + sizeof(v.m) – 1

p = &q->m;
    // lower_bound(p) is (char *)q + offsetof(typeof(*q),  m)
    // upper_bound(p) is lower_bound(p) + sizeof(q->m) – 1

NOTE:

The bounds information is narrowed to the size of the member when you point to a member of a structure, union, or class.

Pointers defined by the new operator

p = new T;
    // lower_bound(p) is (char *)p
    // upper_bound(p) is lower_bound(p) + sizeof(T) - 1

Pointers defined by the addresses in an array

T a[X][Y];

p = a;
p = &a[x];
p = &a[x][y];
    // lower_bound(p) is (char *)a
    // upper_bound(p) is lower_bound(p) + sizeof(a) - 1

When you take the address of an element of an array or the address of a single row of a multi-dimensioned array, the bounds are not narrowed to the size of the element. You can increment or decrement the pointer throughout the array.

Incrementing and Decrementing Pointers

p = &a[x][y].m;
    // lower_bound(p) is (char *)&a[n][m] + offsetof(T, m)
    // upper_bound(p) is lower_bound(p) + sizeof(T.m) – 1

When you take the address of a member of an element, the bounds are narrowed to the size of the member.

Pointers defined by pointer copies

p = q;
p = q + expr;
p = q – expr;
    // lower_bound(p) is lower_bound(q)
    // upper_bound(p) is upper_bound(q)

The bounds are copied from q. Offsetting the pointer on the right does not affect the bounds.

Pointers defined by incrementing or decrementing a pointer

p++;
p--;
++p;
--p;
p += expr;
p -= expr;

The bounds do not change when you increment or decrement a pointer.