Sign in to follow this  
Billy_Thorn

Access violation reading location 0x00000034.

Recommended Posts

"Unhandled exception at 0x0041a024 in Shredding_Legend.exe: 0xC0000005: Access violation reading location 0x00000034." For some reason i receive this error message after running my program, it doesnt even bring up the window or anything, it automatically jumps to this. A few source codes to show:
const_iterator end() const
	{// return iterator for end of nonmutable sequence
		return (const_iterator(_Myhead, this));
	}
List? this is where debugger says the problem is.
//The headers
#include "SDL.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
#include "const.h"
#include "inifile.h"
#include <string>

CIniFile ini;

//Screen attributes
const int SCREEN_WIDTH = atoi( ini.GetSection("Video")->GetKey("Width")->GetValue().c_str() );
const int SCREEN_HEIGHT = atoi( ini.GetSection("Video")->GetKey("Height")->GetValue().c_str() );
const int SCREEN_BPP = 32;

//The frame rate
const int FRAMES_PER_SECOND = 55;
Config.cpp (This is where something is wrong, everything compiles right) i am using Ludvik Jerabek's INI Reader / Writer Class for MFC and ANSI C++(http://www.codeproject.com/KB/cpp/CIniFile.aspx) for the ini loading and stuff. thanks for the help in advanced. Just ask if there s anything that needs to be provided that i didnt.

Share this post


Link to post
Share on other sites
One of your Get... is almost certainly returning null. Trying to access a member of it offsets it by 0x34 bytes, which is then your error location.

Share this post


Link to post
Share on other sites
Not sure about other IDEs but if you are debugging with Visual Studio you can access the call stack in one of the debugging tabs (usually one of the ones on the bottom right of the screen). This is a list of the functions that have been called leading up to the current location (the point where the break occurred). If you click on the last entry in the call stack before it enters the standard library (list functions) it should take you to the line that caused the problem, and allow you to inspect the values of the variables in the watch/auto/locals tabs.

Share this post


Link to post
Share on other sites
Quote:
Original post by b_myeye
Hey,

do you load any file before you use the ini object to get screen width and height?


No, i initially thought that was the problem, only when i tried to load a file before doing so, i could never get the load function to work.

Share this post


Link to post
Share on other sites
I would bet that the problem you were having is that you tried to call the load() function in the global scope, i.e. outside some other function. Apart from variable definitions you can't put non-declaration code outside functions.

Share this post


Link to post
Share on other sites
Shame on your compiler for compiling this. const variables should be set to constants (known at compile time). THis may be causing you issues.

Also, if you are initializing your variables at file scope, you cannot guarantee that "ini" already has a correct value before you initialize you screen size variables - so it is likely returning NULL. This is a recipe for disaster.

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
I would bet that the problem you were having is that you tried to call the load() function in the global scope, i.e. outside some other function. Apart from variable definitions you can't put non-declaration code outside functions.


I am pretty sure thats the problem, but how exactly would i call the load function in the right scope?

Share this post


Link to post
Share on other sites
Quote:
Original post by gpu_fem
Shame on your compiler for compiling this. const variables should be set to constants (known at compile time). THis may be causing you issues.

Actually, it's perfectly legal in C++ for const variables to be initialized dynamically.

Quote:
Also, if you are initializing your variables at file scope, you cannot guarantee that "ini" already has a correct value before you initialize you screen size variables - so it is likely returning NULL. This is a recipe for disaster.

Globals with dynamic initialization are guaranteed to be initialized in order of appearance within a translation unit, which means that ini will be constructed before SCREEN_WIDTH and SCREEN_HEIGHT are initialized. Whether or not the default constructor for CIniFile is a reasonable choice is another story.

edit: grammar

[Edited by - SiCrane on June 9, 2009 7:45:19 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by gpu_fem
Shame on your compiler for compiling this. const variables should be set to constants (known at compile time). THis may be causing you issues.

Not so. Consider the following code:

void example(int x)
{
// this is legal, but not known at compile time.
const int whatever = x;
}



Quote:

Also, if you are initializing your variables at file scope, you cannot guarantee that "ini" already has a correct value before you initialize you screen size variables - so it is likely returning NULL. This is a recipe for disaster.

In a single file, you have guaranteed order of initialisation. It is across files that cause issues. However, in this case the INI constructor probably initialises it to "empty", so yes there will be NULL pointers.

Quote:

I am pretty sure thats the problem, but how exactly would i call the load function in the right scope?

One hackish way is like this:

CIniFile load(const std::string &path)
{
CIniFile file;
file.load(path);
return file;
}

CIniFile ini = load("whatever.ini");


But I wouldn't recommend this approach. It depends on CIniFile respecting the rule of three also.

I think it is best to do this inside main. The primary reason is error handling, outside main there is very little you can do. Because the ini file is external, it needs to be treated as any other form of input and needs to be tested to ensure its correct. You can handle absent values by using defaults, or perhaps informing the user their ini file is corrupted if you cannot read the correct values. But you certainly should not crash for something like this.

Move all the code inside main, and your problems disappear [smile]. Well, not entirely. After all you might be relying on the global values of SCREEN_WIDTH and so on through a number of functions. You could either make them non-const (which is again a bit of a hack) or find other ways to communicate such information. The "best" method depends on the exact kind of information you are trying to access.

Share this post


Link to post
Share on other sites
How you go about putting it in "main?"

The method you gave me didnt work either.


1>c:\documents and settings\user\desktop\c++\shredding_legend\shredding_legend\const.cpp(13) : error C2248: 'CIniFile::CIniFile' : cannot access private member declared in class 'CIniFile'
1> c:\documents and settings\user\desktop\c++\shredding_legend\shredding_legend\inifile.h(157) : see declaration of 'CIniFile::CIniFile'
1> c:\documents and settings\user\desktop\c++\shredding_legend\shredding_legend\inifile.h(49) : see declaration of 'CIniFile'
1>c:\documents and settings\user\desktop\c++\shredding_legend\shredding_legend\const.cpp(16) : error C2248: 'CIniFile::CIniFile' : cannot access private member declared in class 'CIniFile'
1> c:\documents and settings\user\desktop\c++\shredding_legend\shredding_legend\inifile.h(157) : see declaration of 'CIniFile::CIniFile'
1> c:\documents and settings\user\desktop\c++\shredding_legend\shredding_legend\inifile.h(49) : see declaration of 'CIniFile'


Share this post


Link to post
Share on other sites
Quote:

How you go about putting it in "main?"

At the risk of being flippant, before:

//The headers
#include "SDL.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
#include "const.h"
#include "inifile.h"
#include <string>

CIniFile ini;

//Screen attributes
const int SCREEN_WIDTH = atoi( ini.GetSection("Video")->GetKey("Width")->GetValue().c_str() );
const int SCREEN_HEIGHT = atoi( ini.GetSection("Video")->GetKey("Height")->GetValue().c_str() );
const int SCREEN_BPP = 32;

//The frame rate
const int FRAMES_PER_SECOND = 55;





After:

//The headers
#include "SDL.h"
#include "SDL_image.h"
#include "SDL_mixer.h"
#include "const.h"
#include "inifile.h"
#include <string>

int main()
{
CIniFile ini;

ini.Load("config.ini");

//Screen attributes
const int SCREEN_WIDTH = atoi( ini.GetSection("Video")->GetKey("Width")->GetValue().c_str() );
const int SCREEN_HEIGHT = atoi( ini.GetSection("Video")->GetKey("Height")->GetValue().c_str() );
const int SCREEN_BPP = 32;

//The frame rate
const int FRAMES_PER_SECOND = 55;




You can then add in error handling, by first taking the section out and checking its valid, before checking the keys, and finally checking the values. Also, use boost::lexical_cast<> or std::stringstream for converting strings to integers. Using atoi() allows little error checking, as it returns 0 in case of error.

Quote:

The method you gave me didnt work either.

As I said, I don't recommend it. I imagine the reason it doesn't work is because the class does is not copyable. This was alluded to when I said "It depends on CIniFile respecting the rule of three also". But I haven't downloaded the CIniFile code to check.

Share this post


Link to post
Share on other sites
Problem solved.


CIniFile ini;
ini.Load("config.ini");

const int SCREEN_WIDTH = atoi( ini.GetSection("Video")->GetKey("Width")->GetValue().c_str() );
const int SCREEN_HEIGHT = atoi( ini.GetSection("Video")->GetKey("Height")->GetValue().c_str() );

//Set up the screen
screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );



this is the func.cpp function: init()

[Edited by - Billy_Thorn on June 8, 2009 10:44:03 PM]

Share this post


Link to post
Share on other sites
Exactly. Now,

Quote:
Original post by rip-off
You can then add in error handling, by first taking the section out and checking its valid, before checking the keys, and finally checking the values. Also, use boost::lexical_cast<> or std::stringstream for converting strings to integers. Using atoi() allows little error checking, as it returns 0 in case of error.


Here is a helper function you may find helpful:


#include <sstream> // provides std::stringstream.

// I made up the name CIniKeyPtr. You need to replace it with whatever is the
// name of the type returned by GetKey.
int getInt(CIniKeyPtr key) {
// Grab the string and wrap it in a stringstream.
const std::stringstream parser(key->GetValue());
int result;
if (!(parser >> result)) {
throw std::runtime_error("Invalid key data - not numeric");
}
char c;
if (parser >> c) {
throw std::runtime_error("Invalid key data - garbage after the number");
}
return result;
}



Alternatively, if you wrote CIniFile yourself, or have the source for it, you could consider implementing it internally.

Share this post


Link to post
Share on other sites
Hey,

First off good job pointing out the Load() call. Also it should have been documented in my class that if a key doesn't exist the return value is null. So for example

ini.GetSection("Video")->GetKey("Width"); // GetKey can return null as can GetSection

A Clever trick to always ensure your section is not null is using AddSection() it will return an existing section if it exists or create that section if not. As will AddKey(). However if you want to use GetKey properly it is best to do the following.

CIniSection* pSec = iniGetSection("Video");
if( pSec )
{
CIniKey* pKey = pSec->GetKey("Width");
if( pKey )
{
string str = pKey->GetValue();
// Do work here now that all checks passed...
}
}

There are a list of typedef too which can be used instead of CIniSection*, CIniKey* ect.

typedef CIniFile::CIniSection::CIniKey* PCINIKEY;

typedef CIniFile::CIniSection* PCINISEC;

typedef CIniFile* PCINI;


There is also a bug fix I will be posting for the trim string functions. The current ones will not trim if a string is all blank or has tabs and spaces. Replace your functions with these.

void RTrim(std::string &str, const std::string& chars = " \t")
{
str.erase(str.find_last_not_of(chars)+1);
}

void LTrim(std::string &str, const std::string& chars = " \t" )
{
str.erase(0, str.find_first_not_of(chars));
}

void Trim( std::string& str , const std::string& chars = " \t" )
{
LTrim( str , chars );
RTrim( str , chars );
}


Please feel free to contact me if you have any questions in regard to this. Also thanks for using the CIniFile class if you find any bugs please let me know I truly appreciate it.

Thanks,

Ludvik Jerabek

Share this post


Link to post
Share on other sites

The codebase for CIniFile has been re-written provides a much more efficient class supporting unicode and multibyte. The new code uses std::map internally proving to be extremely fast class when using huge ini files.

http://www.codeproject.com/KB/cpp/CIniFile.aspx


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