【问题标题】:memory error (access violation) on method parameters方法参数上的内存错误(访问冲突)
【发布时间】:2012-02-01 22:06:09
【问题描述】:

我遇到了奇怪的问题。我正在尝试用 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 行之后程序会以 Naruszenie ochrony pamięci 停止(内存访问冲突 波兰语)错误。两个Sea::init() 函数似乎都出现了问题。

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

知道它有什么问题吗?

【问题讨论】:

  • 你认为 enemymap 在这一点上是什么?您将 is 声明为 Sea 指针,但从不实例化 Sea 并分配它
  • 博佩尔松所说的。另外,你为什么说(*P1).init(ms)而不是更惯用的P1-&gt;init(ms)

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


【解决方案1】:

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

这样做

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

enemymap 没有指向任何地方时,几乎肯定会导致访问冲突。

【讨论】:

  • 如果您查看代码,每个类都是如此。
  • 是的,代码中有几个类似的问题。 *enemymap 是执行停止的地方,所以我们必须从修复它开始。
  • 鉴于Router 类与Player 所做的事情相同,我想知道它是如何到达那里的(除了愚蠢的、不确定的运气)以get 到它当前崩溃的地方。
  • 我认为这种运气很简单,在其他类中只有指针,而在Sea 类中有更大的结构(二维向量)。
【解决方案2】:

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

这是在 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);
};

【讨论】:

  • 非常感谢 - 它有效。你知道,在 C++ 之前我只写 PHP - 完全不同的哲学。
【解决方案3】:

为博+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 可能不是一个有效的指针。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    • 2013-04-06
    • 1970-01-01
    • 1970-01-01
    • 2017-11-05
    相关资源
    最近更新 更多