Working Dev C++ code won't work in Visual C++

Pages: 123
I've been hacking away at C++ for a few months now, making simple console applications in Dev C++. However, after spending time in this forum and hearing more experienced programmers testify to Dev C++s inadequacies, I decided to make the switch to Visual C++.

But now my one working Dev C++ game won't compile. Actually, the game starts up so it might compile (?), but after the first move I get:

Debug Assertion Failed

Program:...studio 2010\Projects\3D Tic Tac Toe\Debug\3D Tic Tac Toe.exe
File: c:\program files\microsoft visual studio 10.0\vc\include\xstring
Line: 1441

Expression: string subscript out of range



This is from previously working code I posted here a few weeks back and at least one other person compiled successfully. I use String class in the code. Could it have to do with the location of Visual C++ class libraries?
Last edited on
The error is just what the message says, you're having an out-of-bounds access somewhere.
Just because your code seems to be working most of the time doesn't mean it's correct.

Actually, the game starts up so it might compile

If it didn't compile, there wouldn't be anything to start.
Last edited on
The error is just what the message says


but the message references Line 1441 and my code is only 200 lines long?
The error is happening in one of the libraries you're calling (one that handles strings), because you're feeding it bad parameters.

Visual Studio comes with a good debugger. Run it under the debugger and follow the stack up to the line in your code that calls the library.
Last edited on
cool, thanks, but mind if i ask how to do this?
i'm obv pretty new to VC.
Last edited on
Should be a big button near the top somewhere, in that ribbon of buttons. I seem to recall it looks like a little green arrowhead pointing to the right. Failing that, the "F5" key rings a bell in my memory.
ok, yeah, but that seems to have the same effect as what i've been doing all along from the Debug pulldown, then the program runs, but I get the "Assertion Failure" in the same place.

i can't see specifically which line is triggering it. is there a way to tell?

it's happening (i think) during the execution of this function:

1
2
3
4
5
6
7
int normalizeINPUT (string inp) {
    int i, q; 
    string n;
    for (int i=0;inp[i] != '\0';i++) n=n+inp[i];
    q=atoi(n.c_str());
    return q;
}


which i call from main() like this:

1
2
3
4
5
6
7
cout<<"Enter grid number ('Q' to Quit) : ";
          getline (cin,inp);
          if ((inp[0]=='q')||(inp[0]=='Q')) break;
          g=normalizeINPUT(inp);
          if ((g<1)||(g>4)) {cout<<"\nInvalid selection.\n\n";            
                       system("PAUSE");turn--;continue;}
                       


where inp is a string and g is an int. (i know system ("PAUSE") is bad)
i'm thoroughly baffled.
Last edited on
huh. just realized i declared 'i' twice in normalizeINPUT, but fixing it hasn't helped my original problem.
anyone know what all this stuff means?

'3D Tic Tac Toe.exe': Loaded 'C:\Users\Erik\Documents\Visual Studio 2010\Projects\3D Tic Tac Toe\Debug\3D Tic Tac Toe.exe', Symbols loaded.
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\ntdll.dll', Cannot find or open the PDB file
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\kernel32.dll', Cannot find or open the PDB file
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\KernelBase.dll', Cannot find or open the PDB file
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\msvcp100d.dll', Symbols loaded.
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\msvcr100d.dll', Symbols loaded.
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\apphelp.dll', Cannot find or open the PDB file
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\user32.dll', Cannot find or open the PDB file
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\gdi32.dll', Cannot find or open the PDB file
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\lpk.dll', Cannot find or open the PDB file
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\usp10.dll', Cannot find or open the PDB file
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\msvcrt.dll', Cannot find or open the PDB file
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\imm32.dll', Cannot find or open the PDB file
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\msctf.dll', Cannot find or open the PDB file
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\advapi32.dll', Cannot find or open the PDB file
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\sechost.dll', Cannot find or open the PDB file
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\rpcrt4.dll', Cannot find or open the PDB file
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\uxtheme.dll', Cannot find or open the PDB file
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\dwmapi.dll', Cannot find or open the PDB file
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\ole32.dll', Cannot find or open the PDB file
'3D Tic Tac Toe.exe': Loaded 'C:\Windows\System32\cryptbase.dll', Cannot find or open the PDB file
3D Tic Tac Toe.exe has triggered a breakpoint
i'm thoroughly baffled.

So am I.
Why didn't you just write string n=s; instead of that loop?
Or while we're at it, what purpose serves n anyway? Why not this?

1
2
3
int normalizeINPUT (string inp) {
    return atoi(inp.c_str());
}


or rather:
1
2
3
int stringToInt (const string& str) {
    return atoi(str.c_str());
}


If the problem is really caused by that function, it's likely because you're trying to access the element behind the actual string. While this is actually allowed for std::string, VC++ might decide to treat it as an error.
Last edited on
just realized i declared 'i' twice in normalizeINPUT, but fixing it hasn't helped my original problem.

All that happened there was that the i in the loop shadowed the outer i. It made no difference.

anyone know what all this stuff means?

Means you've got no debugging symbols for those files. As a general rule of thumb, the bug will be in your code rather than the libraries, so that's nothing to worry about.

When debugging, you really should be able to access the variables directly and interrogate them to see what values they have. Anyway, as Athar says, your code is far more complicated than it needs to be to turn a string into an int. I see nothing in your code above that looks like you would be stomping over memory that isn't yours, so if this is where the bug is expressed, it's not where it's caused.

Athar- you're right, though in partial defense that loop was a holdover from an earlier version of the program where i used a whitespace instead of a null as an exit condition.... at the time i think i was trying to handle someone entering a huge string of gobbledigoop with whitespaces.

But I just got rid of that function altogether and replaced each function call with

1
2
3
4
5
6
7
getline (cin,inp);
          if ((inp[0]=='q')||(inp[0]=='Q')) break;

          g=atoi(inp.c_str());         //this here where the function call was

          if ((g<1)||(g>4)) {cout<<"\nInvalid selection.\n\n";            
                       system("PAUSE");turn--;continue;}



and it appears to work. but i still don't understand why, or exactly what you mean by "accessing the element behind the string".
string a="42";
That string has length 2, so it has two elements - a[0] and a[1].
However, since neither of those are equal to '\0', your loop keeps going and accesses a[2] - which is out of bounds.
It's still okay, because the standard says that operator[] has to return a reference to a default-initialized instance of the underlying character type (char in this case, so '\0') when you access a[a.length()]. However, this wouldn't have worked if you had used at() instead, for instance.
In an attempt to read Athar's mind...

The std::string type is actually a std::basic_string<char>. In a basic_string, the elements (of type char for a std::string) are stored contiguously in memory (just like an array), which is what allows us to happily use the [] notation to fetch individual characters. However, as Athar says, this is completely within the standard behaviour, and I think it very unlikely that the VS compiler has an issue.

What's definitely happening is that at some point, you're trying to read (or write) to part of the string that doesn't exist, and in debug mode there are things to keep you from doing that (so that you can then fix your code). For example, if you had a string of 4 characters, you'd see this error if you tried to access character -1 (or lower), or 4 (or greater).
Last edited on
ugh, i don't know why i'm not getting this.

Because of where the error was happning, it seemed likely that my problem was in that little function (normalizeINPUT). And this notion is reinforced by the program working with that function removed. The loop in that function is the only line that attempts to access inp.

Now I had thought that a String type was null-terminated like a char*[] array, and that seems to be what Athar is saying here:
It's still okay, because the standard says that operator[] has to return a reference to a default-initialized instance of the underlying character type (char in this case, so '\0') when you access a[a.length()]


The loop does check inp[inp.len()] for it's exit condition, but it doesn't modify it, and i don't see how it differs from this other code from C++ Without Fear:

1
2
3
4
char *str="Hello!";
do { 
       //stuff
       }  while (*p++)


won't this also look ahead for the null value?

...but thanks guys, i guess my VC is functional.
Last edited on
This code demonstrates reading every character in a std::string, and then choosing to read beyond the size of the string. We find that it is indeed null-terminated. However, to find out, we had to read beyond the size of string. Your debug runtime is keeping track of the size of the array for you, and when you try to read beyond the size of the array, it stops you. This means that you cannot use the mechanism of finding the null-terminator in a std::string (under the debug runtime you're using), because to find it, you must read beyond the end of the array.

I suspect that the code below will not work on your setup; however, it should work fine if you don't use the debug runtime that does you the favour of checking your array access. A better way is to just read the size of the string, as below (for(int i=0; i<aString.size(); ++i) )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <string>
#include <iostream>

int main()
{
  std::string aString("Eggs on toast");
  std::cout << aString << std::endl;

  std::cout << "Size of the string is " << aString.size() << std::endl;

  for(int i=0; i<aString.size(); ++i)
    { std::cout << i << ":" << aString[i] << std::endl;
    }

  std::cout << "Value of size+1 element is " << (int)aString[aString.size()+1];
  return 0;
}

Last edited on
thanks Moschops, helpful as usual.

marking it solved for now, though i obviously still have a bit to learn about how the compiler handles char*....
i don't see how it differs from this other code from C++ Without Fear:

The difference that in that example, it's a C string and those are null-terminated by definition. That means "Hello!" is an array of 7 characters - 6 for Hello! and a final '\0'. That's not true for C++ strings. When you assign "Hello!" to a std::string, it will contain 6 characters, not 7.
When you assign "Hello!" to a std::string, it will contain 6 characters, not 7.


thanks Athar, i did not know this.
In C++11 std::string is null terminated and you can treat it as such except when using iterators. VC++ has apparently not updated this yet.
Pages: 123