Jump to content
  • Advertisement
Sign in to follow this  
3dmodelerguy

Access Violation?

This topic is 3699 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have the following code from the building a scripting language tutorial:
#include <iostream>
#include <conio.h>
#include <vector>
#include <assert.h>

enum opcode{op_talk, op_end, op_print};

class instruction
{
        public:
                instruction(opcode code) : _code(code), _data(0) {}
                instruction(opcode code, const char* data, size_t data_size) : _code(code), _data(new char[data_size])
                {
                        memcpy(_data, data, data_size);
                }
                ~instruction()  { delete[] _data; }
                opcode code() const { return _code; }
                const char* data() const    { return _data; }

        private:
                opcode _code;
                char* _data;
};

class script
{
        public:
                script(const std::vector<instruction> &instruction_list) : _instruction_list(instruction_list){}
                const instruction* instruction_pointer() const { return &_instruction_list[0]; }
        private:
                std::vector<instruction> _instruction_list;
};

class virtual_machine
{
        public:
                virtual_machine() : _script_pointer(0), _instruction_pointer(0), _instruction(0), _script_count(0) {}
                
                // a very basic interface
                inline void execute(size_t script_id);
                size_t load(const script& script)   { return add_script(script); }
                
        private:  // useful abstractions
                typedef const script* script_reference;
                typedef const instruction*  instruction_reference;
                // pointers used as non-modifying dynamic references
                private:  // utilities
                size_t add_script(const script& script) // add script to list and retrieve id
                {
                                _script_list.push_back(script);
                                return _script_count++;
                }
                void select_script(size_t index)    // set current script by id
                {
                        assert(index < _script_count);  // make sure the id is valid
                        _script_pointer = &_script_list[index];
                        _instruction_pointer = _script_pointer->instruction_pointer();
                } 

        private:  // data members
                std::vector<script> _script_list;
                script_reference _script_pointer;    // current script
                instruction_reference _instruction_pointer;     // root instruction
                instruction_reference _instruction;        // current instruction
                size_t _script_count;  // track the loaded scripts
};

void virtual_machine::execute(size_t script_id)
{
        select_script(script_id);  // select our _instrPtr by script ID
        _instruction = _instruction_pointer;      // set our iterator to the beginning
        while (_instruction)
        {
                switch(_instruction->code())
                {
                        case op_talk:
                                std::cout << "I am talking." << std::endl;
                                ++_instruction;  // iterate
                                break;

                        case op_print:
                                //std::cout << _instruction->data() << std::endl;
                                ++_instruction;  // iterate
                                break;

                        case op_end:
                                _instruction = 0;  // discontinue the loop
                                break;
                }
        }
}

int main()
{
        virtual_machine vm;

        char* buffer = "this is printed data";

        // build the script
        std::vector<instruction> instruction_list;
        instruction_list.push_back(instruction(op_talk)); // talk twice
        instruction_list.push_back(instruction(op_print, buffer, strlen(buffer) + 1));
        instruction_list.push_back(instruction(op_talk)); // talk twice
        instruction_list.push_back(instruction(op_end));  // then end
        //script script(instruction_list);

        // load the script and save the id
        //size_t script_id = vm.load(script);

        // execute the script by its id
        //vm.execute(script_id);
        _getch();
}



but when I run this I get a access violation reading location, anyone know why since the code it pretty much the same as the tutorial as of right now? [Edited by - 3dmodelerguy on May 5, 2008 10:03:47 PM]

Share this post


Link to post
Share on other sites
Advertisement
Probably because your instruction class doesn't obey the rule of three. In particular, you're lacking a valid copy constructor and assignment operator.

Share this post


Link to post
Share on other sites
Quote:
Original post by 3dmodelerguy
I have the following code from the building a scripting language tutorial:


I have no idea what tutorial you're talking about, but in C++, we normally represent text strings with std::string.

As it stands, your 'instruction' objects cannot safely be copied, because trying to copy them will just copy the '_data' pointer, and not the pointed-at data. When both the copy and original object die, they will both try to delete[] the same data. That's not allowed.

Not being able to copy the objects is bad. When you put things into a container, the container will copy the objects behind the scenes. In a few different situations, including the initial insertion into the container. After all, it can't very well just steal your local variable away from you, hmm?

Solution: use std::string to represent text strings, the way we normally do in C++.

Also, don't artificially pause your program at the end, please. Learn to run it properly, instead.


#include <iostream>
#include <string>
#include <vector>
#include <cassert> // it is not called assert.h any more.

enum opcode{op_talk, op_end, op_print};

class instruction
{
public:
instruction(opcode code) : _code(code), _data() {}
instruction(opcode code, const std::string& data, size_t data_size) : _code(code), _data(data) {}
opcode code() const { return _code; }
const std::string& data() const { return _data; }

private:
opcode _code;
std::string _data;
};


Share this post


Link to post
Share on other sites
Ok i have modified the code to the following(sorry I can't seem to figure out how to do a code block like Zahlman did, helo with that would be good):


#include <iostream>
#include <conio.h>
#include <vector>
#include <cassert>
#include <string>

enum opcode{op_talk, op_end, op_print};

class instruction
{
public:
instruction(opcode code) : _code(code), _data(0) {}
instruction(const instruction& copy_instruction)
{
_code = copy_instruction._code;
_data = copy_instruction._data;
}
instruction(opcode code, const std::string& data) : _code(code), _data(data){}
~instruction() {}
opcode code() const { return _code; }
const std::string data() const { return _data; }

private:
opcode _code;
std::string _data;
};

class script
{
public:
script(const std::vector<instruction> &instruction_list) : _instruction_list(instruction_list){}
const instruction* instruction_pointer() const { return &_instruction_list[0]; }
private:
std::vector<instruction> _instruction_list;
};

class virtual_machine
{
public:
virtual_machine() : _script_pointer(0), _instruction_pointer(0), _instruction(0), _script_count(0) {}

// a very basic interface
inline void execute(size_t script_id);
size_t load(const script& script) { return add_script(script); }

private: // useful abstractions
typedef const script* script_reference;
typedef const instruction* instruction_reference;
// pointers used as non-modifying dynamic references
private: // utilities
size_t add_script(const script& script) // add script to list and retrieve id
{
_script_list.push_back(script);
return _script_count++;
}
void select_script(size_t index) // set current script by id
{
assert(index < _script_count); // make sure the id is valid
_script_pointer = &_script_list[index];
_instruction_pointer = _script_pointer->instruction_pointer();
}

private: // data members
std::vector<script> _script_list;
script_reference _script_pointer; // current script
instruction_reference _instruction_pointer; // root instruction
instruction_reference _instruction; // current instruction
size_t _script_count; // track the loaded scripts
};

void virtual_machine::execute(size_t script_id)
{
select_script(script_id); // select our _instrPtr by script ID
_instruction = _instruction_pointer; // set our iterator to the beginning
while (_instruction)
{
switch(_instruction->code())
{
case op_talk:
std::cout << "I am talking." << std::endl;
++_instruction; // iterate
break;

case op_print:
//std::cout << _instruction->data() << std::endl;
++_instruction; // iterate
break;

case op_end:
_instruction = 0; // discontinue the loop
break;
}
}
}

void main()
{
virtual_machine vm;

std::string buffer = "this is printed data";

// build the script
std::vector<instruction> instruction_list;
instruction_list.push_back(instruction(op_talk)); // talk twice
instruction_list.push_back(instruction(op_print, buffer));
instruction_list.push_back(instruction(op_talk)); // talk twice
instruction_list.push_back(instruction(op_end)); // then end
//script script(instruction_list);

// load the script and save the id
//size_t script_id = vm.load(script);

// execute the script by its id
//vm.execute(script_id);
_getch();
}




and still getting the same access violation. I am quite confused about this issue as a few people on IRC have said it should work.

also the tutorial series i am talking about is this one(the first of 5 i think) http://www.gamedev.net/reference/articles/article1633.asp. I just wanted to following the tutorial till the end and then start modify things.

[Edited by - 3dmodelerguy on May 5, 2008 10:35:03 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by 3dmodelerguy
Ok i have modified the code to the following(sorry I can't seem to figure out how to do a code block like Zahlman did, helo with that would be good)


Reading the FAQ could help. Use [ source ][ /source ]

About your problem, on which line are you getting an access violation ?

Share this post


Link to post
Share on other sites
Quote:

sorry I can't seem to figure out how to do a code block like Zahlman did, helo with that would be good


Just put your code inside [ source ][ /source ] tags (without the spaces).

Share this post


Link to post
Share on other sites
Here :

instruction(opcode code) : _code(code), _data(0) {}


"_data(0)" is calling this constructor :

basic_string(
const value_type* _Ptr,
const allocator_type& _Al = Allocator ( )
);


That's why you're getting an access violation, this constructor expects a C-string. Use _data(""), or don't call the constructor at all :

instruction(opcode code) : _code(code) {} // should work



Anyway, there might be other problems in your code if you have just text-replaced char* by std::string... Think before/while you're writing, not after

Share this post


Link to post
Share on other sites
Quote:
Original post by 3dmodelerguy
yea the _data was the issue. funny enough std::string works were char* as in the tutorial does not for some reason.

char* are evil

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!