Sign in to follow this  
leet bix

"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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
phresnel    953
Quote:
Original post by leet bix
but 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 this post


Link to post
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 this post


Link to post
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 pointer

char **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 = 1

char 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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
phresnel    953
Quote:
by DevFred
Are 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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
phresnel    953
Quote:
Original post by leet bix
it'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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
phresnel    953
Quote:
Original post by leet bix
often 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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this