方法参数的内存错误(访问冲突)

时间:2012-02-01 22:06:09

标签: c++ memory-management segmentation-fault

我有一个奇怪的问题。我正在尝试用C ++编写简单的游戏,但我在对象和数据类型上失败了。有一个代码:

// 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;
}

它可以被编译,但在行 Init 5×5 map 程序停止与 Naruszenieochronypamięci内存访问违规在波兰语中)错误。两个Sea::init()函数似乎都出现了问题。

我正在使用g++ -std=c++0x -Wno-write-strings ships2.cpp(以防止警告)在Ubuntu上编译它。

知道它有什么问题吗?

3 个答案:

答案 0 :(得分:2)

所有类都包含指针,但您似乎永远不会初始化指针或为它们应指向的对象分配空间。

这样做

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

enemymap未指向任何地方时,几乎可以肯定地获取访问权限。

答案 1 :(得分:0)

您正在使用未初始化的指针。您可以通过在此处实例化对象或在其他位置的构造函数中来修复它。

以下是在initmap调用中实例化的示例。

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);
};

答案 2 :(得分:0)

+1的博。但是为了你自己:

用-g编译然后再用

编译
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);

这应该告诉你P1可能不是一个有效的意思。