# "Vector subscript out of range" error

## Recommended Posts

leet bix    116
I've been getting this odd error on my DirectX app, first, I create an array of LPCSTRing's (this is just a character format incase you haven't encountered if before), and fill it like so
	LPCSTR cCubeMapDirectories[9];
cCubeMapDirectories[0] = "Media/LightProbes/uffizi_cross.dds";
cCubeMapDirectories[1] = "Media/LightProbes/beach_cross.dds";
cCubeMapDirectories[2] = "Media/LightProbes/building_cross.dds";
cCubeMapDirectories[3] = "Media/LightProbes/rnl_cross.dds";
cCubeMapDirectories[4] = "Media/LightProbes/stpeters_cross.dds";
cCubeMapDirectories[5] = "Media/LightProbes/grace_cross.dds";
cCubeMapDirectories[6] = "Media/LightProbes/campus_cross.dds";
cCubeMapDirectories[7] = "Media/LightProbes/galileo_cross.dds";
cCubeMapDirectories[8] = "Media/LightProbes/kitchen_cross.dds";


I then pass this array to the 'create' function of a skybox class like so;
hr = g_SkyBox.CreateSkyBox(g_pd3dDevice,
&BackBufferDesc,
50,
cCubeMapDirectories,
"Media/Effects/SkyBox.fx");


I then copy it into a vector of LPCSTRing's in the class like so
for(int i = 0; i < sizeof(strCubeMapFilePaths); i++)
{
m_EnvironmentMapDirs.push_back(strCubeMapFilePaths[i]);
}

// the data member m_EnvironmentMapDirs is private and declared as such:

std::vector<LPCSTR> m_EnvironmentMapDirs;	// stores paths for light probes


After this, I have a function that allows me to set the current light probe cube map based on an index passed to it, the index is also stored in a UNIT data member in the private section of the class, the function for navigating is as follows;
	/******SetEnvironmentMapByIndex*******/
HRESULT SetEnvironmentMapByIndex(UINT uiIndex)
{
// make sure that the index is in the arrays range
if(uiIndex < 0 || uiIndex > m_EnvironmentMapDirs.size())
return E_FAIL;

HRESULT hr;
SAFE_RELEASE(m_pEnvironmentMap);

IDirect3DCubeTexture9* pCubeTexture = NULL;
hr = D3DXCreateCubeTextureFromFileEx(m_pd3dDevice, m_EnvironmentMapDirs[uiIndex], D3DX_DEFAULT, 1, 0, D3DFMT_A16B16G16R16F,
D3DPOOL_MANAGED, D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR, 0, NULL,
NULL, &pCubeTexture);

CHECK_RESULT(hr, "Could not set environment by index");

m_pEnvironmentMap = pCubeTexture;
m_EnvironmentMapIndex = uiIndex;

return hr;
}


although, what happens when I get to the 5th element (m_EnvironmentMapDirs[4]) is that I get a debug assertion error saying "Expression: vector subscript out of range" and the debug points me here
[source lang"cpp"]
// this is in the vector file

#if _HAS_ITERATOR_DEBUGGING
if (size() <= _Pos)
{
_DEBUG_ERROR("vector subscript out of range");
_SCL_SECURE_OUT_OF_RANGE;
}


I don't see how I am trying to access a member of the vector outside of it's range when it's size is 9, any ideas?

##### Share on other sites
DevFred    840
What is the value of sizeof(strCubeMapFilePaths)?
std::cout << sizeof(strCubeMapFilePaths) << std::endl;

##### Share on other sites
leet bix    116
Oh wow it's saying 4, should have tested that, but really I have no idea why this is happening.

##### Share on other sites
Zao    971
Applying the sizeof operator to an array gives you the size of the array in bytes. If you want the number of elements, use (sizeof arr)/(sizeof arr[0]).
However, in your case, your array has decayed into a pointer. Applying the sizeof operator to a pointer gives you the size of the pointer in bytes. Which on your platform is 4.

##### Share on other sites
leet bix    116
Thanks, I see why it was returning 4 now :) I thought that if I was to use strCubeMapFilePaths weather or not it was passed in as a pointer it would always be a pointer, nurmeous articles say that an array without the square brackets is just a pointer to the first element?
I've tried using this for loop;

for(int i = 0; i < sizeof(strCubeMapFilePaths) / sizeof(strCubeMapFilePaths[0]); i++)	{		m_EnvironmentMapDirs.push_back(strCubeMapFilePaths[i]);	}

but it doesn't work past the first element (element 0)

##### Share on other sites
phresnel    953
It is probably 4 because you are probably doing applying sizeof onto a pointer type (you are on a 32bit box, right?).

Can we see the defintion of "strCubeMapFilePaths" and how you initialize it?

Hint: Why not use a standard container?

edit: D'Oh, ninja'd.

##### Share on other sites
phresnel    953
Quote:
 Original post by leet bixbut it doesn't work past the first element (element 0)

Probably (can we see the definition of strCubeMapFilePaths?) because strCubeMapFilePaths is a pointer, not an array. Read Zao's post carefully.

##### Share on other sites
leet bix    116
I've ended up just doing this instead,

hr = g_SkyBox.CreateSkyBox(g_pd3dDevice, &BackBufferDesc, 50, cCubeMapDirectories, sizeof(cCubeMapDirectories), "Media/Effects/SkyBox.fx");

just passing in sizeof(array) to the function, I assume there's a way of doing it within the function?

##### Share on other sites
phresnel    953
You haven't read our replies to you, have you??

Not even this tiny bit:
Quote:
 my humble self(can we see the definition of strCubeMapFilePaths?)

Meh...

char *s = "asdsad";   << sizeof (s) = 4, because s is a pointerchar **s = "asdsad";  << sizeof (s) = 4, because s is a pointer                         sizeof (*s) = 4, because *s is a pointer                         sizeof (**s) = sizeof(char), because **s is a char                         sizeof(s)/sizeof(*s) = 4/4 = 1char s[7] = "asdsad"; << sizeof (s) = 7*sizeof (char), because s is an array                         sizeof(s)/sizeof(char) = 7

(on x86 processors, pointers are generally 4 bytes (32 bits) long, on x64, they are 8 bytes (64 bits) long; in the above example, I assumed you are on a x86 architecture)

Seriously, A) read what others replied to you and B) as you are in C++, why not use containers and string of the standard library?

[Edited by - phresnel on May 4, 2009 3:05:18 AM]

##### Share on other sites
jyk    2094
Like the previous posters, I recommend using a container class of some sort instead of a raw array. The most logical choice would probably be boost/tr1::array. Using array will eliminate the need to track the size of the array separately, and will provide other benefits as well (such as range-checking).

##### Share on other sites
DevFred    840
Are you sure passing sizeof(cCubeMapDirectories) to the function gives the correct value?
Because sizeof(someArray) gives you the number of bytes, not the number of elements.
std::cout << sizeof(cCubeMapDirectories) << std::endl;

##### Share on other sites
leet bix    116
it's returning 36, this is becoming rather frustrating ><

##### Share on other sites
phresnel    953
Quote:
 by DevFredAre you sure passing sizeof(cCubeMapDirectories) to the function gives the correct value?

Quote:
 leet bix LPCSTR cCubeMapDirectories[9]; cCubeMapDirectories[0] = "Media/LightProbes/uffizi_cross.dds"; cCubeMapDirectories[1] = "Media/LightProbes/beach_cross.dds"; cCubeMapDirectories[2] = "Media/LightProbes/building_cross.dds"; cCubeMapDirectories[3] = "Media/LightProbes/rnl_cross.dds"; cCubeMapDirectories[4] = "Media/LightProbes/stpeters_cross.dds"; cCubeMapDirectories[5] = "Media/LightProbes/grace_cross.dds"; cCubeMapDirectories[6] = "Media/LightProbes/campus_cross.dds"; cCubeMapDirectories[7] = "Media/LightProbes/galileo_cross.dds"; cCubeMapDirectories[8] = "Media/LightProbes/kitchen_cross.dds";

Hence
sizeof(cCubemap) = sizeof(char*) * 9 = 4*9[x86]

##### Share on other sites
leet bix    116
I've fixed it, by taking the size in bytes of the array and dividing it by the size of a single element, cheers everyone for your help =)

##### Share on other sites
jyk    2094
Quote:
 it's returning 36, this is becoming rather frustrating ><
The reason for this has already been explained (three times, by my count), so you might want to give the previous replies another read.

##### Share on other sites
phresnel    953
Quote:
 Original post by leet bixit's returning 36, this is becoming rather frustrating ><

WE HAVE DONE YOU A FAVOR BY SPENDING SOME OF OUR PRECIOUS TIME TO ANSWER YOUR QUESTION ...

Why can't you just read them or elaborate further what you don't understand from our posts?

##### Share on other sites
leet bix    116
My apologies, I'm rather tired and have said that I already got it, thank you for your time.

##### Share on other sites
jyk    2094
Quote:
 I've fixed it, by taking the size in bytes of the array and dividing it by the size of a single element, cheers everyone for your help =)
Good :) Now, why not just use boost/tr1::array?

##### Share on other sites
leet bix    116
I prefer not using the boost libraries, as it is rather large and often ends up including a lot of stuff that you don't really need, also from what I understand, parts of it will be implemented as standard C++ am I right?

##### Share on other sites
phresnel    953
Quote:
 Original post by leet bixoften ends up including a lot of stuff that you don't really need

Not really.

But boost aside, why not use the standard library of C++2003 (<vector>, <list>, <string>)?

Quote:
 , also from what I understand, parts of it will be implemented as standard C++ am I right?

Indeed.

Btw, here you can see which core language features of C++0x are supported by GCC 4.4, here is the status of GCC's standard library implementation. According to it, it already has array<> (complete overview is here).

##### Share on other sites
jyk    2094
Quote:
 I prefer not using the boost libraries, as it is rather large and often ends up including a lot of stuff that you don't really need...
What are your concerns exactly? Increased build times? Larger executables? Something else? And have you actually run into problems using Boost, or are you just avoiding it based on the expectation of problems?

I ask this because people often seem to have misconceptions about how the Boost libraries work exactly. Most of the commonly used parts of Boost are header-only, which means no linking. You use it just like you would the standard library; include the appropriate header(s), and go.

Some of the include trees do go pretty deep, and to be honest I'm not sure exactly what the array header pulls in. However, unless you have specific evidence that using boost::array will impact your project negatively, I strong suggest that you go ahead and give it a try.
Quote:
 also from what I understand, parts of it will be implemented as standard C++ am I right?
Yes, and you can certainly just use the tr1 version if you have it available.

##### Share on other sites
leet bix    116
I installed the boost library around 6 months ago and used some of the pointer functions, I then started exploring some more of the library and it was quiet overwhellming just looking at the size and documentation, that would probably be my primary reason for not wishing to use it if I can do something another way.

##### Share on other sites
jyk    2094
Quote:
 I installed the boost library around 6 months ago and used some of the pointer functions, I then started exploring some more of the library and it was quiet overwhellming just looking at the size and documentation, that would probably be my primary reason for not wishing to use it if I can do something another way.
The C++ standard library is also big and complicated, and with C++0x, it's become even more so. I don't know every corner of the standard library and I'm going to guess that you don't either, but you don't let that stop you from using the parts that you find useful, do you?

Just as with the SC++L, Boost is not an all-or-nothing proposition; you can just use the parts that you find useful and leave the rest. It's like a big toolbox - you just reach in and grab what you need. There are all sorts of arcane tools rattling around at the bottom, but that doesn't mean you can't use the screwdriver sitting right there at the top, right?

As for the Boost documentation, don't let the enormity of it put you off. Although you can certainly peruse it if it interests you, it's not really meant to be read all at once. Again, just refer to the parts that you need.

##### Share on other sites
Zahlman    1682
Yes, the libraries will pull in a lot of stuff you apparently don't need. Like, for example, solutions that work with minimal effort and neatly sidestep additional problems that you'll invariably have further down the road with your current approach.