"Vector subscript out of range" error

Started by
22 comments, last by Zahlman 14 years, 11 months ago
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);
	}

// 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?
Advertisement
What is the value of sizeof(strCubeMapFilePaths)?
std::cout << sizeof(strCubeMapFilePaths) << std::endl;
Oh wow it's saying 4, should have tested that, but really I have no idea why this is happening.
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.

To make it is hell. To fail is divine.

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);	}


but it doesn't work past the first element (element 0)
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.
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.
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?
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]
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).

This topic is closed to new replies.

Advertisement