C++ map lower_bound causes debug assertion failed - visual-c++

I'm using Visual Studio 2012.
I made a class for a map like this:
classA
{
private:
string a;
string b;
uint32_t start;
uint32_t end;
};
and I defined a map and a function like this:
typedef std::map<uint32_t, classA, std::greater<uint32_t> > ClassAMap;
typedef ClassAMap::iterator ClassAMapIterator;
ClassAMap classAMap;
void lowerBoundTest(ClassAMap &classAMap)
{
uint32_t test = 0;
ClassAMapIterator it;
cin >> hex >> test;
it = classAMap.lower_bound(test);
cout << "lower_bound of " << test << ": "
<< it->first << endl;
}
then I got this error when dereferencing iterator of the map.
Debug Assertion Failed!
Program: C:\Windows\system32\MSVCP110D.dll
File: C:\program files (x86)\microsoft visual studio 11.0\vc\include\xtree
Line: 137
Expression: map/set iterator not dereferencable
For information on how your program can cause an assertion failure,
see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
I don't get any error message when I define a map like this:
typedef std::map<uint32_t, classA> ClassAMap;
typedef ClassAMap::iterator ClassAMapIterator;
But I need to put a greater<> function for purpose.
How can I get rid of this assertion failure?

lower_bound will return the iterator equal to the map's end() when the item you're searching for isn't in the map, and it's insertion point would be at the end of the map. Since end() is one past the end of the map, it doesn't point to a valid element of the map. Trying to dereference it is an error. Be lucky that you were running this in Debug mode with a checked iterator, otherwise you'd have just gotten undefined behavior instead of a nice error message.
The reason it changes when you order the map without greater is that it changes the order of the map; lower_bound is now returning begin() instead of end(), which is a valid element.
To see whether the element was found in the map, you should use equal_range instead of lower_bound and check that the two iterators are not equal. The first of the two is identical to what lower_bound returns.

Related

Unable to use Iterator for a MAP to PRINT STRING. (able to print int)

I tried printing a string in the MAP using iterator but I am getting an error.
Program -
#include<iostream>
#include<stdio.h>
#include<conio.h>
#include<map>
#include<string.h>
#include<unordered_map>
using namespace std;
void main()
{
std::map<int,std::string>mymap;
std::map<int,std::string>::iterator it;
mymap.insert(make_pair(10, "sid"));
mymap.insert(make_pair( 20, "sam"));
for (it = mymap.begin(); it != mymap.end(); it++)
{
//printf("%s \n", it->second);
std::cout <<*it->second << std::endl;
}
system("pause");
_getch;
}
Error list
1.Error C2679 binary '<<': no operator found which takes a right-hand
the operand of type 'std:: string' (or there is no acceptable conversion)
2.Error (active) no operator "<<" matches these operands
I was able to print the int properly. I am unable to print the STRING. Please suggest a solution.
That's not how you access the object pointed to by the iterator.
Just use cout<< it->second<<endl;.
All the errors are then automatically resolved.
P.S. Refer to my comment on your question.

How can I get the value of a registry key in c++ without an access violation?

Hey I'm new to C++ and I am trying to find out if a specified registry index exists. I have to check multiple locations due to the possibility of the software being run on a 64bit machine and being under the WOW6432Node key instead of the usual position. When RegQueryValueExA (using visual c++ 6.0 on xp so I can't use a newer function) is run it should return a Boolean of true if the key exists, (I'll deal with getting the value of the key later). However on run it generates access violation 0xc00005. Any ideas whats gone wrong?
bool FindAndRemoveUninstall(string path){
bool result;
result = RegQueryValueExA(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ABC"), NULL, NULL, NULL, (unsigned long *)MAX_PATH);
if (result= ERROR_SUCCESS){
cout <<" is a 32 bit program\n";
//path= Value in key
}
result = RegQueryValueEx(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ABC"), NULL, NULL, NULL, (unsigned long *)MAX_PATH);
if (result= ERROR_SUCCESS){
cout << " is 64 bit program\n";
//path= Value in key
}
return true;
}
You have multiple problems.
The last parameter to RegQueryValueExA is documented as
lpcbData [in, out, optional]
A pointer to a variable that specifies the size of the buffer pointed to by the lpData parameter,
But you are not passing a pointer to a variable. You are passing (unsigned long *)MAX_PATH, which is a garbage pointer. When the operating system tries to store the result into the pointer, it takes an access violation. You need to pass a pointer to a variable, like the documentation says.
The next problem is that you are calling the A function (explicit ANSI) but using the TEXT macro (adaptive character set). Make up your mind which model you are using (ANSI or adaptive) and choose one model or the other. Let's assume you explicit ANSI.
The next problem is that you didn't specify an output buffer, so you don't actually retrieve the path.
Another problem is that the RegQueryValueExA function does not return a bool; it returns an error code.
Yet another problem is that your if test contains an assignment, so it does not actually test anything.
Another problem is that you didn't specify a way for the function to return the path to the caller. Let's assume you want the result to be returned in the path parameter.
Yet another problem is that you have the 32-bit and 64-bit cases reversed.
Also, you are using '\n' instead of std::endl.
The eight problem is that your function returns true even if it didn't do anything.
And the ninth problem is that the function says FindAndRemove, and it finds, but doesn't remove.
bool FindUninstall(string& path){ // parameter passed by reference, fix function name
LONG result; // change variable type
char buffer[MAX_PATH]; // provide an output buffer
DWORD bufferSize = MAX_PATH; // and a variable to specify the buffer size / receive the data size
result = RegQueryValueExA(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ABC", NULL, NULL, (LPBYTE)buffer, &bufferSize); // remove TEXT macro, pass the buffer and buffer size
if (result== ERROR_SUCCESS){ // fix comparison
cout <<" is a 64 bit program" << std::endl; // fix message
path = buffer;
return true; // stop once we have an answer
}
buffersize = MAX_PATH; // reset for next query
result = RegQueryValueEx(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ABC", NULL, NULL, (LPBYTE)buffer, &bufferSize); // remove TEXT macro, pass the buffer and buffer size
if (result== ERROR_SUCCESS){ // fix comparison
cout << " is 32 bit program" << std::endl; // fix message
path = buffer;
return true; // stop once we have an answer
}
return false; // nothing found
}
Since you are new to C++, I would recommend that you get some experience with C++ doing simpler projects before diving into more complicated things like this.

Visual Studio '13 (Access Violation)

When I compile and run this program via gcc(g++)/Cygwin it compiles and acts as expected.
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
for (int arg = 1; arg <= argc; arg++)
{
cout << argv[arg] << endl;
}
return 0;
}
However, when compiling with Visual Studio 13, the program compiles but I am given an access violation upon execution. What gives?
Unhandled exception at 0x000B5781 in demo.exe: 0xC0000005: Access violation reading location 0x00000000.
argv is a pointer to the first element of an array containing argc+1 elements. The first argc elements of this array contain pointers to first elements of null terminated strings representing the arguments given to the program by the environment (commonly the first of these strings is the name of the program, followed by the command line arguments).
The last element of this array (the argc+1th element, which argv[argc] refers to) is a null pointer. Your code dereferences this null pointer, leading to undefined behaviour.
The important thing to note here is that array indexing in C++ is zero based, rather than one based. This means that the first element of an array arr of length n is arr[0], and the last element is arr[n-1]. Your code appears to assume that the first element of such an array is arr[1] and that the last element is arr[n].

Having trouble passing array to function

I am getting all kinds of errors when passing my array to this function. The function is suppose to have the user enter a name and a score and store them in 2 seperate arrays, one for the names, one for the scores. I believe I have to use pointers but have no idea on how to use them. I don't want the answer, just a push in the right direction. Here is the code:
#include <iostream>
int InputData(int &, char, int);
using namespace std;
int main()
{
char playerName[100][20];
int score[100];
int numPlayers = 0;
InputData(numPlayers, playerName, score);
return 0;
}
int InputData(int &numPlayers, char playerName[][20], int score[])
{
while (numPlayers <= 100)
{
cout << "Enter Player Name (Q to quit): ";
cin.getline(playerName, 100, ā€˜\nā€™);
if ((playerName[numPlayers] = 'Q') || (playerName[numPlayers] = 'q'))
return 0;
cout << "Enter score for " << playerName[numPlayers] <<": ";
cin >> score[numPlayers];
numPlayers++;
}
}
Ok, I made some more changes and the errors are less, must be getting close, Lol!
This looks like a school assignment and I applaud you for not asking for the answer. There are several ways to do it, but you are already fairly close in the approach that you are using. When you pass an array reference, you do not want to include the length of the array. For example, the parameter int score[100] should be int score[]. The exception, especially in your scenario, is with multidimensional arrays. In this case, you want to use char playerName[][20]. Your function declaration also needs to change to match. Don't forget InputData returns an int. Your declarations and function call are correct; you just need to adjust your function signature.
Keeping the errors aside -
InputData(numPlayers, playerName, score, size);
// ^^^^ size is no where declared
// resulting Undeclared indentifier error
Prototype mentions of taking 3 arguments but calling the function passing 4 parameters.
Hint regarding errors:
An 1D array decays to a pointer pointing to first element in the array while passing to a function.
A 2D array decays to a pointer pointing to the 1D array ( i.e., T[][size] ) while passing to a function.
Return type of main() should be int.
It seems with the given hints you corrected most of the errors. But you forgot to change the prototype. So, change -
int InputData(int &, char, int);
to
int InputData(int &, char[][20], int[]);
Why aren't you using std::string array for player names ? Use it and remove rest of the errors. Good luck.

Reading a value in associative array creates a new key

I have code such as this. I use
pvalueholder is class that is polymorphic , it can hold all sort of types, string..etc..
It also can have a type undefined.
typedef hash_map<pvalueholder,pvalueholder,pvaluehasher > hashtype;
hashtype h;
pvalueholder v;
v="c";
h[v]=5; // h has one element
pvalueholder v2=h[v]; // here h gets a new key/value how is that possible?
cout << (string) (h[v]) << endl; // here h gets another new key/value how is that possible?
int i =0;
for (hashtype::iterator h1=h.begin(); h1!=h.end();h1++)
{
cout << "no: " << i++ << endl;
} // this prints three lines, it should print one...
Two values are undefined here, the third one is 5 as expected.
size_t pvaluehasher::operator() (const pvalueholder& p) const
{
cout << "hashvalue:" << p.value->hashvalue() << endl;
return p.value->hashvalue();
}
returns
Here is what is printed:
hashvalue:84696444
hashvalue:84696444
hashvalue:84696444
returns:1
hashvalue:84696444
returns:1
hashvalue:84696444
returns:1
returns:1
hashvalue:84696444
Do you have any ideas what it may be?
Thank you.
Solution:
the function operator()(parameter1,parameter2) needs to be different in case of Microsoft STL.
For microsoft, it needs to return less than relationship between parameter1 and parameter2.
For gcc, it needs to return equality. I returned equality.
The comparison function for the keys was not correct...
The function returned true for equality while it has to return less than in case of Microsoft STL.
My guess would be that your hash function is incorrect - meaning it produces different hash values given the same key "c".
Show the declaration for pvalueholder and full code for pvaluehasher.
It's almost impossible to comment on hash_map, because it's never been standardized, and the existing implementations aren't entirely consistent. Worse, your code doesn't seem to be correct or compilable as it stands -- some places the value associated with the key seems to be an int, and other places a string.
Using std::tr1::unordered_map and fixing the rest of the code to compile and seem reasonable, like this:
#include <unordered_map>
#include <iostream>
#include <string>
using namespace std;
typedef std::tr1::unordered_map<std::string, int> hashtype;
std::ostream &operator<<(std::ostream &os, std::pair<std::string, int> const &d) {
return os << d.first << ": " << d.second;
}
int main() {
hashtype h;
std::string v = "c";
h[v]=5; // h has one element
int v2=h[v];
cout << h[v] << endl;
int i =0;
for (hashtype::iterator h1=h.begin(); h1!=h.end();h1++)
{
cout << *h1 << endl;
} // this prints three lines, it should print one...
return 0;
}
The output I get is:
5
c: 5
This seems quite reasonable -- we've inserted only one item, as expected.
Solution: the function operator()(parameter1,parameter2) needs to be different in case of Microsoft STL. For microsoft, it needs to return less than relationship between parameter1 and parameter2. For gcc, it needs to return equality. I returned equality. The comparison function for the keys was not correct... The function returned true for equality while it has to return less than in case of Microsoft STL.

Resources