#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();
}
Access Violation?
I have the following code from the building a scripting language tutorial:
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]
Probably because your instruction class doesn't obey the rule of three. In particular, you're lacking a valid copy constructor and assignment operator.
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;};
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):
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]
#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]
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 ?
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).
Here :
"_data(0)" is calling this constructor :
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 :
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
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
yea the _data was the issue. funny enough std::string works were char* as in the tutorial does not for some reason.
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
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement