error de memoria (violación de acceso) en los parámetros del método

I've got weird problem. I'm trying to write simple game in C++, but I failed on objects and data types. There's a code:

// C++
// Statki

#include <stdio.h>
#include <time.h>
#include <map>
#include <vector>
#include <string>
#include <list>

#define D true

using namespace std;

void _(char* message){printf("%s\n",message);};

struct relpoint { int x,y; };
struct point { int x,y; };
struct size { int w,h; };

map<const char*, vector<relpoint> > shipshape;
list<char*> shipTypes = {"XS", "S", "M", "L", "XL"};

string alpha="ABCDEFGHIJKLMNOPRSTUVWXYZ";

enum fieldtype { UNKNOWN=-1,EMPTY=0,SHIP=1,HIT=2,MISS=3,};

enum rotation { EAST=0, SOUTH=1, WEST=2, NORTH=3 };

class Ship
{
    char* type;

};

class Sea
{
    public:
    void init(size mapsize) { init( mapsize, EMPTY ); };
    void init(size mapsize, fieldtype fill)
    {
        if(D)printf("Generating sea\n");
        vector<fieldtype> v;

        seamap.reserve(mapsize.h);
        v.reserve(mapsize.w);

        for (int y=0; y<mapsize.h; y++)
        {
            v.clear();
            for(int x=0; x<mapsize.w; x++)
            {
                v.push_back(fill);
            }
            seamap.push_back(v);
        }

        view();
    };

    bool place_ship(Ship ship);

    void view()
    {
        for( vector< vector<fieldtype> >::const_iterator yy = seamap.begin(); yy != seamap.end(); ++yy )
        {
            for( vector<fieldtype>::const_iterator xx = (*yy).begin(); xx != (*yy).end(); ++xx )
            {
                if(D)printf("%d ", *xx);
            }
            if(D)printf("\n");
        }
    };

    private:
    vector< vector<fieldtype> > seamap;
};

class Game
{
    public:

    void initmap(size mapsize)
    {
        if(D) printf("\nInit %d×%d map\n", mapsize.w, mapsize.h);

        (*enemymap).init(mapsize, UNKNOWN);
        //(*selfmap).init(mapsize);
    };

    bool placeship(string type, point position, rotation rotate);
    fieldtype shoot(point target);
    void viewmap(){(*selfmap).view();};

    bool eog();

    Sea * enemymap;
    Sea * selfmap;
};

class Bot
{
    public:

    void init(size mapsize)
    {
        if(D)_("Init Bot");
    }

    private:

    Game * g;
};

class Player
{

    public:
    Player() { if(D){_("Player fake init");} };

    void init(size mapsize)
    {
        (*g).initmap(mapsize);
    };

    void viewmap(){(*g).viewmap();};

    private:
    Game * g;

};

class Router
{

    public:

    void startgame();
    void welcomescreen()
    {
        printf("\n\n\n\t\t\tShips minigame\n\t\t\t\tby Kris\n\n");

        mainmenu();
    };
    void mainmenu()
    {
        printf("Menu (type letter):\n\tN: New game\n\tS: Settings\n\tQ: Quit game\n\n > ");

        char opt;
        opt = toupper(getchar());

        size ms;

        switch(opt)
        {
            case 'N':
                ms = getmapsize();
                (*P1).init(ms);
                (*P2).init(ms);
            break;

            case 'S':

            break;

            case 'Q':

            break;

            default:
                printf("Invalid option %c", opt);
                mainmenu();
        }
    };

    private:
    Player * P1;
    Bot    * P2;

    size getmapsize()
    {
        size ms;
        printf("\nSet map size (X Y)\n > ");
        scanf("%d %d", &ms.w, &ms.h);
        return ms;
    };
};

int main () {

    vector<relpoint> shp;
    shp.reserve(5);
    list<char*>::const_iterator tp = shipTypes.begin();
    shp.push_back({0,0});
    shipshape[*(tp++)] = shp;
    shp.push_back({1,0});
    shipshape[*(tp++)] = shp;
    shp.push_back({2,0});
    shipshape[*(tp++)] = shp;
    shp.push_back({3,0});
    shipshape[*(tp++)] = shp;
    shp.push_back({2,1});
    shipshape[*tp] = shp;

    Router R;
    R.welcomescreen();

    printf("\n\n");
    return 0;
}

It can be compiled, but after line Init 5×5 map program stops with Naruszenie ochrony pamięci (Memory access violation in polish) error. Problem seems to occur at both Sea::init() funciones.

Lo estoy compilando con g++ -std=c++0x -Wno-write-strings ships2.cpp (to prevent warnings) on Ubuntu.

¿Alguna idea de lo que tiene de malo?

preguntado el 01 de febrero de 12 a las 22:02

Qué piensas enemymap is at that point? You declare is as a Sea pointer but never instantiate a Sea and assign it -

What Bo Persson said. Also, any reason why you say, for example, (*P1).init(ms) instead of the more idiomatic P1->init(ms)? -

3 Respuestas

All the classes contain pointers, but you never seem to initialize the pointers or allocate space for the objects they should point to.

Haciendo esto

 (*enemymap).init(mapsize, UNKNOWN);

cuando enemymap doesn't point anywhere, is an almost sure way to get an access violation.

Respondido 02 Feb 12, 02:02

If you look through the code this is the case in every class. - Brian Roach

Yes there are several similar problems in the code. The *enemymap is the place where the execution stopped, so we have to start by fixing that. - Bo Persson

I'm wondering how it even got there (other than by dumb, undefined luck) given that the Router class does the same thing as does Player para obtener to where it's currently crashing. - Brian Roach

I think this luck is simply that in other classes there are only pointers and in Sea class there are mayores structure (2d vector). - Arrvi

You are using an uninitialized pointer. You can fix it by instantiating an object here, or in a constructor somewhere else.

Here is an example of instantiating in the initmap call.

void initmap(size mapsize)
{
    // Initialize the pointer by instantiating a class
    enemymap = new Sea;
    if(D) printf("\nInit %d×%d map\n", mapsize.w, mapsize.h);

    (*enemymap).init(mapsize, UNKNOWN);
    //(*selfmap).init(mapsize);
};

Respondido 02 Feb 12, 02:02

Thanks a lot - it works. You know, before C++ I was writing only PHP - completely different philosophy. - Arrvi

+1 for Bo. But for your own sake:

compile with -g and then then

gdb ./mygame.bin
type 'run'

after setting the map size 5 5 :

Program received signal SIGSEGV, Segmentation fault.
mainmenu (this=<optimized out>) at memacvio.cpp:158
158                 (*P1).init(ms);

This should tell you that P1 is probably not a valid poiner.

Respondido 02 Feb 12, 02:02

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.