Sign in to follow this  
ajm113

std::find, std::end, Exception Error, C++

Recommended Posts

Hello, I get a exception error on this line:
if(m_mpTextures.find( szFile ) != m_mpTextures.end()){




m_mpTextures And szFile are defined like so:
//In a class
std::map<const char*, NodeTexture*, TextureCompare> m_mpTextures;

//szFile Proccess
char *szFile;
szFile = new char[strlen(szFilename)+1];
	strcpy(szFile, szFilename);

	_strlwr( szFile );

//Then if(m_mpTextures.find( ... and so forth.


Can someone suggest what to do? I am not very good with exceptions that well.. the szFile goes through a process that gives it a value so it isn't NULL. VS2005/C++/Win32

Share this post


Link to post
Share on other sites
Quote:
Original post by ajm113
Hello, I get a exception error on this line:


I'm afraid you'll have to tell us exactly what error or exception you get.

Share this post


Link to post
Share on other sites
That's not going to work like you think it should. char *'s are not strings, so the map will not do a strcmp when it tries to find them (unless you're providing your own comparison function), it will check if the pointer addresses are equal. Use std::strings if you want to use strings as map keys.

I suspect your exception is an access violation because you aren't properly allocating the char*'s you're using as keys. Can we see where in code you do that?

Share this post


Link to post
Share on other sites
Well I get this exception error:

Unhandled exception at 0x6b94704d (msvcp80d.dll) in main.exe: 0xC0000005: Access violation reading location 0x03010101.

@Driv3MeFar, sorry I am a bit light headed right now, but I don't believe I did that in my code for char *s. Can you give me a small example what you would do?

Share this post


Link to post
Share on other sites
We'd need to see the code for TextureCompare in order to understand what is causing the crash.
However you could probably make the problem go away by just using "std::string" instead of "const char *". That'd make it a whole lot easier too.

Share this post


Link to post
Share on other sites
Quote:
Original post by ajm113
Well I get this exception error:

Unhandled exception at 0x6b94704d (msvcp80d.dll) in main.exe: 0xC0000005: Access violation reading location 0x03010101.

@Driv3MeFar, sorry I am a bit light headed right now, but I don't believe I did that in my code for char *s. Can you give me a small example what you would do?


He would just use std::string, and so would I.

Share this post


Link to post
Share on other sites

struct TextureCompare {
bool operator() (const char* s1, const char* s2) const {
return strcmp(s1, s2) < 0;
}

};




Sorry for the late reply, no one was replying a while ago, so I thought this thread was already dead.

But I tried std::strings, but they don't work that well what I been playing with.

Share this post


Link to post
Share on other sites
Quote:
Original post by ajm113
Sorry for the late reply, no one was replying a while ago, so I thought this thread was already dead.

But I tried std::strings, but they don't work that well what I been playing with.
You'll find that most of us here disagree. std::strings are what works well, it's char*'s that don't work well. If you think otherwise then you're probably doing it wrong.

Don't forget that people replying here come from all sorts of time zones. As such some people wont get to read other's replies for perhaps at least 24 hours.

Share this post


Link to post
Share on other sites
Ok, so how do I do this? I already tried changing szFile and making a local string variable out of m_mpTextures, I keep getting errors, can you tell me a correct way on doing this?


Tried #1

std::string TexturesTemp = m_mpTextures;

if(TexturesTemp.find(szFile) != TexturesTemp.end()){





Tried #2

if(m_mpTextures.find((std::string)szFile) != m_mpTextures.end()){


Share this post


Link to post
Share on other sites
Like this perhaps:

typedef std::map<std::string,NodeTexture*> TextureMap;
TextureMap textures;

// in some function
std::string name = /* whatever */;

TextureMap::iterator it = textures.find(name);
if(it != textures.end())
{
// more code
}


Better still to use a smart pointer for the NodeTextures.

Share this post


Link to post
Share on other sites
Quote:
Original post by ajm113
Ok, so how do I do this? I already tried changing szFile and making a local string variable out of m_mpTextures, I keep getting errors, can you tell me a correct way on doing this?


Tried #1
*** Source Snippet Removed ***


Tried #2
*** Source Snippet Removed ***


m_mpTextures is your map. You can't just turn the map into a string.

What we are suggesting is that you use std::string as the key type of the map.


std::map<std::string, NodeTexture*> m_mpTextures; // no comparison function is needed

// Copying the filename is as simple as copying an int:
std::string szFile = szFilename;
// If _strlwr() really is sufficient for you for the purpose of putting a
// string in "lowercase" (that only works for a few languages), then the
// following is fine in C++:
for (int i = 0; i < szFile.size(); ++i) { szFile[i] = tolower(szFile[i]); }

std::map<std::string, NodeTexture*>::iterator it = m_mpTextures.find(szFile);
if (it != m_mpTextures.end()) {
// it->first is szFile; it->second is the NodeTexture*
}


Of course, in my own code, I would have much nicer variable names :)

Share this post


Link to post
Share on other sites
Ok, I do have to keep that one function in the map other wise all the other functions besides my texture loader is going to have problems..

std::map<const char*, NodeTexture*, TextureCompare> m_mpTextures;

This is what I have:



char *szFile;
szFile = new char[strlen(szFilename)+1];
strcpy(szFile, szFilename);

//_strlwr( szFile );


// Copying the filename is as simple as copying an int:
std::string szFile2 = szFile;

for (int i = 0; i < szFile2.size(); ++i) { szFile2[i] = tolower(szFile2[i]); }

std::map<std::string, NodeTexture*>::iterator it = m_mpTextures.find(szFile);
if (it != m_mpTextures.end()) {






Errors:
error C2440: 'initializing' : cannot convert from 'std::_Tree<_Traits>::iterator' to 'std::_Tree<_Traits>::iterator'

error C2678: binary '!=' : no operator found which takes a left-hand operand of type 'std::_Tree<_Traits>::iterator' (or there is no acceptable conversion)

Share this post


Link to post
Share on other sites
Quote:
Original post by ajm113
Ok, I do have to keep that one function in the map other wise all the other functions besides my texture loader is going to have problems..

std::map<const char*, NodeTexture*, TextureCompare> m_mpTextures;

This is what I have:

*** Source Snippet Removed ***

Errors:
error C2440: 'initializing' : cannot convert from 'std::_Tree<_Traits>::iterator' to 'std::_Tree<_Traits>::iterator'

error C2678: binary '!=' : no operator found which takes a left-hand operand of type 'std::_Tree<_Traits>::iterator' (or there is no acceptable conversion)


Why do you have to keep the map storing char*'s? What problems will switching it to strings cause?

In the code you posted you have a std::map<const char*, NodeTexture*, TextureCompare> which you are trying to iterate into with a std::map<std::string, NodeTexture*>::iterator. This isn't going to work. A std::map<const char*, NodeTexture*, TextureCompare> is not a std::map<std::string, NodeTexture*>.

Also, post the code where you actually are storing values in this map. I suspect you aren't properly allocating your char* keys, which caused the original problem.

Share this post


Link to post
Share on other sites
ok, I fallow a bit, how do I "properly allocating your char* keys"?

[EDIT]
mmm, ok I changed all the maps to string, but I run into this:


for(std::map<std::string, NodeTexture*, TextureCompare>::iterator it = m_mpTextures.begin(); it != m_mpTextures.end(); it++) {
delete it->second;
delete [] it->first; //C2440

}
m_mpTextures.clear();
} //DeleteAllTextures



error C2440: 'delete' : cannot convert from 'const std::string' to 'void *'

Share this post


Link to post
Share on other sites
The reason that things aren't working correctly for you is that you persist in using raw pointers to store text. This is a terrible idea. It is extremely brittle, as you are learning right now.

To break down what you need to do:

1) Change the type of m_mpTextures to std::map<std::string,NodeTexture *>.

2) Make your iterator type match the map type. The easiest way to do this is to use typedef, as I illustrated a few posts ago.

3) Clean up the rest of the interface so that you accept const std::string references, not char pointers.

Between the examples that myself and Zahlman posted you should be able to do this.

The only issue unresolved in these examples is that you want lowercase only strings. You can implement your own comparator functor that does this, or manually place the strings in lowercase as they come into this module. If your module is properly designed, there will only be few places you need to do this anyway. The custom comparator is probably easier to maintain, especially when used with typedef.

If there is anything you don't understand, ask. But do yourself a favour and forget that you ever could use char pointers as std::map<> keys. Or forget about using them for text, in general [smile].

[edit] this was a reply to your original, unedited post.

Share this post


Link to post
Share on other sites
Ok, I did what you said and replaced all functions that take in const char that have to do with that map into a string and used c_str() in those char * required functions, what I am not understanding is that I keep getting 17 of these errors:

error C2784: 'bool std::operator <(const std::vector<_Ty,_Alloc> &,const std::vector<_Ty,_Alloc> &)' : could not deduce template argument for 'const std::vector<_Ty,_Alloc> &' from 'const std::string' c:\program files\microsoft visual studio 8\vc\include\functional 143

error C2784: 'bool std::operator <(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)' : could not deduce template argument for 'const std::_Tree<_Traits> &' from 'const std::string' c:\program files\microsoft visual studio 8\vc\include\functional 143


Can you suggest what to do? I am kinda stuck in a tight hall way.

@ rip-off Ok, thanks now I now know I don't need to delete strings.

Share this post


Link to post
Share on other sites
Huh, how does an error relating to a vector now come into this?
I think you better post the lines of code that produce those errors.

Share this post


Link to post
Share on other sites
Quote:
Original post by ajm113
Ok, I did what you said and replaced all functions that take in const char that have to do with that map into a string and used c_str() in those char * required functions, what I am not understanding is that I keep getting 17 of these errors:

error C2784: 'bool std::operator <(const std::vector<_Ty,_Alloc> &,const std::vector<_Ty,_Alloc> &)' : could not deduce template argument for 'const std::vector<_Ty,_Alloc> &' from 'const std::string' c:\program files\microsoft visual studio 8\vc\include\functional 143

error C2784: 'bool std::operator <(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)' : could not deduce template argument for 'const std::_Tree<_Traits> &' from 'const std::string' c:\program files\microsoft visual studio 8\vc\include\functional 143


Did you remember to #include <string> ?

Share this post


Link to post
Share on other sites
[Edit] Wow, I thought I added it already! That's strange, I'll ask you any more questions when I compile my project. I don't have VS2005 STD at the moment. I think the cd is screwed up, because it won't complete Windows Document (something) at the end of the installation.

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