3

次のように定義されたデータメンバーとしてを持つクラスMessageがあります。std::string

class Message
{
// Member Variables
    private:
        std::string text;
        (...)

// Member Functions
    public:
        Message(const std::string& t)
        : text(t) {}

        std::string getText() const {return text;}
        (...)
};

このクラスは、次のように別のクラスのベクトルで使用されます。

class Console
{
// Member Variables
    private:
        std::vector<Message> messageLog;
        (...)

// Member Functions
    public:
        Console()
        {
            messageLog.push_back(Message("Hello World!"));
        }

        void draw() const;
};

にはdraw()、 を呼び出すイテレータがありますgetText()。その場合、プログラムはセグメンテーション違反を起こします。コンストラクターtext内で有効であると判断しました。Messageただし、内部から有効かどうかはわかりませんConsole。私はそうであると仮定していますが、Consoleの messageLog のインデックスを調べようとすると、gdb は次のように教えてくれます:

(gdb) p messageLog[0]
One of the arguments you tried to pass to operator[] could not be converted to what the function wants.

何が起こっているか知っている人はいますか?

編集:ここにありますdraw()TCODConsole私が使用している curses ライブラリの一部であるため、この関数は各メッセージをConsolecurses 画面の一部に出力します。 TLBRPoint、画面上のどこに描画するかを示すメンバー オブジェクト (2 つの int) ですConsole。うまくいけば物事を明確にするために元の質問の一部Messageを省略しましたが、クラス全体を投稿する必要がある場合は、投稿できます。Console長すぎません。

void Console::draw() const
        {
            int x = TL.getX(), y = TL.getY();
            int width = BR.getX() - TL.getX();
            int height = BR.getY() - TL.getY();

            // draw the Console frame
            TCODConsole::root->printFrame(x, y, width, height, true);

            // print the Console's messages
            vector<Message>::const_iterator it;
            for(it=messageLog.begin(); it<messageLog.begin()+height-1; ++it)
            {
                string message = "%c" + it->getText();
                TCODConsole::setColorControl(TCOD_COLCTRL_1, 
                                             it->getForeColor(),
                                             it->getBackColor());
                y += TCODConsole::root->printRectEx(x, y, width, height,
                                                    TCOD_BKGND_NONE,
                                                    TCOD_LEFT,
                                                    message.c_str(),
                                                    TCOD_COLCTRL_1);
            }
        }
4

4 に答える 4

2

私の推測では、 を使用する時点it->getText()で、イテレータは NULL になっています。it != messageLog.end()配列をウォークするとき、および を呼び出す前にチェックを追加しますit->getText()

于 2010-06-21T22:19:17.973 に答える
0

高さとベクトルのインデックスの関係は? あなたが持っている:

messageLog.begin()+height-1;

画面座標をイテレータに追加するのはなぜですか? それがあなたの問題のようであり、おそらくオーバーインデックスを作成しているため、SIGSEGV を取得しています。

おそらくあなたが望むのは、ベクター内のすべてのメッセージを単純に繰り返し処理し、それらを画面上の特定の場所に表示することです。あなたがやろうとしていることはわかりますが、イテレータを使用して画面の境界を計算しようとしている場合は、間違いなく間違った方法で行っています。カウンターを実行するか、取得messageLog.size()してから、各反復で高さを再計算してみてください。ループに関しては、次のようにします。

for(it=messageLog.begin(); it!=messageLog.end(); ++it)
于 2010-06-21T22:22:29.403 に答える
0

それは間違いなくstd::vector messageLogそうではありませんstd::vector<Message> messageLogか?それは少し奇妙に思えます。

于 2010-06-21T21:42:25.293 に答える
-2

これMessageは、メソッドで作成されたオブジェクトのスコープConsoleが単なるメソッドであることが原因である可能性がありますConsole。したがって、プログラムがなどの別のメソッドでこのオブジェクトにアクセスしようとするとdraw、このオブジェクトは実行後に削除されるため、このセグメンテーション違反が発生します。

newこれを試してください(キーワードを挿入するだけです):

    Console()
    {
        messageLog.push_back(new Message("Hello World!"));
    }

この場合、コンソールの終了後にオブジェクトは削除されません。

プログラムで作成されたオブジェクトが不要になったときに削除することを忘れないでください。

于 2010-06-21T21:56:38.633 に答える