Thread: Why isn't map::find() finding anything?

  1. #1
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545

    Why isn't map::find() finding anything?

    Can anyone think of a reason why map::find() isn't finding a name that definitely is in the map?
    Code:
    typedef std::map<std::wstring, bool>	UserAdminChangeMap;
    std::wstring strUserName( UserName->Buffer, UserName->Length );			// strUserName == L"Test1"
    UserAdminChangeMap::iterator it = g_UserAdminChangeMap.find( strUserName );	// map has 1 key == L"Test1"
    
    if ( it != g_UserAdminChangeMap.end() )
    {
    	if ( it->second == true )
    	{
    		swprintf( GenericMessage, _T("*** User '&#37;s' with admin flag found in map!"), strUserName.c_str() );
    	}
    	else
    	{
    		swprintf( GenericMessage, _T("*** User '%s' WITHOUT admin flag found in map!"), strUserName.c_str() );
    	}
    
    	g_UserAdminChangeMap.erase( it );
    }
    else
    {
    	it = g_UserAdminChangeMap.begin();
    	swprintf( GenericMessage, _T("*** User (%04x %04x %04x %04x %04x %04x) NOT found in map!\nmap size = %u\nmap.first = (%04x %04x %04x %04x %04x %04x)"),
    			strUserName.c_str()[0], strUserName.c_str()[1], strUserName.c_str()[2], strUserName.c_str()[3], strUserName.c_str()[4], strUserName.c_str()[5],
    			g_UserAdminChangeMap.size(),
    			it->first.c_str()[0], it->first.c_str()[1], it->first.c_str()[2], it->first.c_str()[3], it->first.c_str()[4], it->first.c_str()[5] );
    }
    It prints this into GenericMessage:
    Code:
    *** User (0054 0065 0073 0074 0031 0000) NOT found in map!
    map size = 1
    map.first = (0054 0065 0073 0074 0031 0000)
    Last edited by cpjust; 07-18-2008 at 08:44 AM.

  2. #2
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    have you tried stripping whitespace, etc ?

  3. #3
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by m37h0d View Post
    have you tried stripping whitespace, etc ?
    From where?
    The strings are exactly the same. Both are "Test1" and I even checked the hex values of the characters in case there was some strange Unicode difference, but they're both (0054 0065 0073 0074 0031 0000)

  4. #4
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    I just tried changing my map to a vector and it still doesn't find it:
    Code:
    typedef std::vector<std::wstring>	UserAdminChangeMap;
    
    UserAdminChangeMap::iterator it = std::find( g_UserAdminChangeMap.begin(), g_UserAdminChangeMap.end(), strUserName );

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Stupid question: Does g_UserAdminChangeMap.begin().str() == strUserName give you true or false?

  6. #6
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by tabstop View Post
    Stupid question: Does g_UserAdminChangeMap.begin().str() == strUserName give you true or false?
    Good question, I'll try that out. It just takes a long time because every time I change the code in this DLL I need to reboot since it's loaded by LSA...

    I also checked the .size() of each string, and for some reason it reported 10 instead of 5, so when I looked at all 10 hex bytes, the values were different after the NUL char:
    Code:
    *** User (0054 0065 0073 0074 0031 0000 0000 0000 8234 6670)[10] NOT found in map!
    map size = 1
    map.first = (0054 0065 0073 0074 0031 0000 ffff ffff ffff ffff)[10]
    Maybe the UserName->Length that LSA passes is wrong? I'll check that too.

  7. #7
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Oh crap! I just looked at the documentation for PUNICODE_STRING again and saw that Length is in bytes, not in TCHARS. Doh!

  8. #8
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    YES!!! I changed it to this, and now everything works fine!
    Code:
    std::wstring strUserName( UserName->Buffer, (UserName->Length / sizeof(WCHAR)) );

  9. #9
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    I guess one other thing I learned with this mess is that std::string's == operator doesn't compare NUL terminated strings; it compares every character in it's buffer, even if there's a NUL in the middle of it.

  10. #10
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Yes, in compares everything up to size(). Incidentally, I believe std::map uses operator< (by default) for comparing but that doesn't change anything.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  11. #11
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by anon View Post
    Yes, in compares everything up to size(). Incidentally, I believe std::map uses operator< (by default) for comparing but that doesn't change anything.
    Yes, maps compare for equivalence rather than equality. i.e. if ( !(a < b) && !(b < a) )
    I don't really need that bool parameter in the map anyways, so I just kept it as a vector.

  12. #12
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    I don't really need that bool parameter in the map anyways, so I just kept it as a vector.
    std::set ?
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  13. #13
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by Cactus_Hugger View Post
    std::set ?
    I just thought of that when I got home.
    It's unlikely that a UserID would be pushed onto the vector and not removed by the other thread, but with this spagetti code anything is possible, so using a std::set would at least minimize a possible memory leak to a much smaller size.

  14. #14
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    Quote Originally Posted by cpjust View Post
    I just thought of that when I got home.
    It's unlikely that a UserID would be pushed onto the vector and not removed by the other thread, but with this spagetti code anything is possible, so using a std::set would at least minimize a possible memory leak to a much smaller size.
    If you're using std::string/std::wstring contained in a std::map/std::set, there shouldn't be any leaking, unless you're doing something really wrong. The nice thing about std::string, set, map, etc. is that they help reduce the coded needed to avoid leaking. My main motive for suggesting std::set is that finding userIDs would be O(log(n)) instead of O(n)

    Be sure that access to the container and its contents is thread-safe, of course.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  15. #15
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by Cactus_Hugger View Post
    If you're using std::string/std::wstring contained in a std::map/std::set, there shouldn't be any leaking, unless you're doing something really wrong. The nice thing about std::string, set, map, etc. is that they help reduce the coded needed to avoid leaking. My main motive for suggesting std::set is that finding userIDs would be O(log(n)) instead of O(n)

    Be sure that access to the container and its contents is thread-safe, of course.
    Oh thanks, that's another good reason to use a std::set that I didn't think of.
    The "memory leak" I was talking about is that I have 1 function adding users to the vector and another taking them off the vector. If something goes wrong and the 2nd function doesn't get called and therefore never removes the users from the vector, it would keep getting bigger and bigger. Also, since vectors allow duplicate entries, it grows indefinitely, whereas a std::set doesn't allow duplicates, so even if the users aren't removed, there wouldn't be that many users in the company to cause a huge memory leak. But that's just a cover my ass scenario, since I can't see a reason why the 2nd function wouldn't get called.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. tools for finding memory leaks
    By stanlvw in forum C++ Programming
    Replies: 4
    Last Post: 04-03-2009, 11:41 AM
  2. Finding primes
    By starripper in forum C++ Programming
    Replies: 19
    Last Post: 01-14-2006, 04:17 PM
  3. ROW OPERATIONS (finding Inverse) (im going crazy)
    By alexpos in forum C Programming
    Replies: 1
    Last Post: 11-20-2005, 10:07 AM
  4. MFC :: Finding Child Window of a CWnd* Object?
    By SyntaxBubble in forum Windows Programming
    Replies: 2
    Last Post: 09-06-2003, 09:06 AM
  5. Finding the algorithm that's right for you.
    By sean in forum A Brief History of Cprogramming.com
    Replies: 3
    Last Post: 02-03-2002, 10:03 AM