mpen
mpen

Reputation: 283173

Is it safe to read past the end of an array?

Let's say I have a constructor like this:

MyColor(uint8 vec[]) {
r = vec[0];
g = vec[1];
b = vec[2];
a = vec[3];
}

But I call it like this (3 elements instead of 4):

uint8 tmp[] = {1,2,3};
MyColor c(tmp);

But now vec[3] is undefined... is it safe to assign this value to a? If not, there's no nice workaround to check if vec[3] is set is there?

Upvotes: 3

Views: 1510

Answers (8)

In C++, as in C, on function arguments arrays decay into pointers. Now, depending on the semantics of the function you can use other approaches:

// explicit parameters (with or without default values):
mycolor( uint8_t r, uint8_t g, uint8_t b, uint8_t alpha = 255 );

// vector (can check length)
mycolor( std::vector<uint8_t> const & components );

// array by reference
mycolor( uint8_t (&components)[ 4 ] );

The first approach to me is the cleanest.

Upvotes: 2

newbie
newbie

Reputation: 71

if you dont want to use vector try this...

MyColor(uint8 (&vec)[3])
{
   r = vec[0];
   g = vec[1];
   b = vec[2];
}

MyColor(uint8 (&vec)[4])
{
   //...
}

uint8 a1[] = {1,2,3};
MyColor c1(a1);
uint8 a2[] = {1,2,3,4};
MyColor c2(a2);
uint8 a3[] = {1,2,3,4,5};
MyColor c3(a3); // error

you dont have to include the array's size explicitly and if you try to pass an array with wrong number of elements, compile error will be generated,

Upvotes: 3

Secko
Secko

Reputation: 7716

It's like you'r asking if it's safe to build a house on top of a lake. One day you may wake up in the water.

In your case you may find that a dangling pointer can cause unstability and frequent crashes to the system.

If you know what a dangling pointer is you now what the risk is.

Upvotes: 0

Roman Pl&#225;šil
Roman Pl&#225;šil

Reputation: 1970

No, this is not safe. Maybe you would like to pass the coordinates as parameters to constructor and use two overloads:

MyColor(uint8 a, uint8 b, uint8 c, uint8 d) {
    stuff
}

MyColor(uint8 a, uint8 b, uint8 c) {
    stuff
}

This way you can use both

MyColor a(1, 2, 3);
MyColor b(1, 2, 3, 4);

Upvotes: 4

sth
sth

Reputation: 229784

No, it's not safe. You're reading memory that you have not allocated, and this is undefined behavior. Depending on the phase of the moon you might or might not get a segmentation fault.

To "work around" it, make sure the array you pass in has always the correct size. In your example you could do:

uint8 tmp[4] = {1,2,3};
MyColor c(tmp);

The initializer doesn't need to specify all the elements of the array that gets created, so it's ok to just initialize the first three values explicitly. The remaining values will be set to zero.

Upvotes: 12

vehomzzz
vehomzzz

Reputation: 44628

The shown behavior is undefined, and likely to crash down the road.

I would recommend to use vector along, and access elements using vector::at() call. That will throw an exception if went beyond alloted bounds. Ensure to reserve enough space in the vector

Upvotes: 1

Billy ONeal
Billy ONeal

Reputation: 106609

Nope. It's possible this causes a segfault.

Billy3

Upvotes: 1

Mehrdad Afshari
Mehrdad Afshari

Reputation: 422162

No it's not safe. It's undefined behavior as defined by the standard. It might blow the whole app up or return a random value. The workaround is to pass the size along with it, or use vector instead.

Upvotes: 18

Related Questions