小さなコード変更の背後にあるsegfaultの根本原因を突き止めようとしています。のは、問題なく実行されるコードのこの簡易版、始めましょう:どうやらテールノードが悪い親を取得するようC++のポインターとクラス階層がセグメンテーションパズルを起こしています
今#include <iostream>
#include <string>
#include <vector>
class GameObject {
public:
virtual void update();
void addChild(GameObject* child);
GameObject* parent;
std::vector<GameObject*> children;
int x;
int y;
};
class Player : public GameObject {
public:
void growTail();
void update();
};
class TailNode : public GameObject {
public:
void addTo(GameObject* parent);
void update();
// UPDATE AFTER ANSWER IS CLEAR: this was in original codebase and it was causing the segfault
GameObject* parent;
};
void GameObject::addChild(GameObject* child) {
this->children.push_back(child);
child->parent = this; // <- can't do this in full codebase, causes segfault later
}
void GameObject::update() {
for (GameObject* child : children) {
child->update();
}
}
void Player::update() {
GameObject::update();
std::cout << "Player at: ["
<< std::to_string(x)
<< std::to_string(y)
<< "]"
<< std::endl;
}
void Player::growTail() {
TailNode* tail = new TailNode();
tail->addTo(this);
}
void TailNode::update() {
GameObject::update();
std::cout << "Tail parent at: ["
<< std::to_string(parent->x) // <- if parent is set inside GameObject::addChild, this segfaults in full codebase
<< std::to_string(parent->y)
<< "]"
<< std::endl;
}
void TailNode::addTo(GameObject* parent) {
parent->addChild(this);
// this->parent = parent; <-- have to do this to avoid segfault in full codebase
}
int main() {
Player* player = new Player();
player->x = 10;
player->y = 11;
player->growTail();
player->update();
}
、ゲームのソース自体に、それは、セグメンテーションフォルトを行います。
child->parent = this;
をGameObject::addChild
に移動し、this->parent = parent;
をTailNode::addTo
に移動すると動作します。
私はそれがポインターに関連していると推測しています。私はそれらを悪用しています。
あなたはhttps://github.com/spajus/sdl2-snake/tree/tail_working で完全に動作するコードベースを見つけ、それを壊すことにコミットすることができます:https://github.com/spajus/sdl2-snake/commit/4e92e9d6823420ce7554f2b6d7d19992c48d4acc
私はOS X 10.11.5上でそれをコンパイルし、実行している、
Apple LLVM version 7.3.0 (clang-703.0.31)
Target: x86_64-apple-darwin15.5.0
Thread model: posix
を
コードが依存していますSDL2とその拡張のいくつか。
例のコンパイルコマンド:
$XCODE/XcodeDefault.xctoolchain/usr/bin/c++ \
-I/Library/Frameworks/SDL2.framework/Headers \
-I/Library/Frameworks/SDL2_image.framework/Headers \
-I/Library/Frameworks/SDL2_mixer.framework/Headers \
-I/Library/Frameworks/SDL2_ttf.framework/Headers \
-I$HOME/Dev/sdl2-snake/include \
-Wall -Wextra -pedantic -std=c++11 \
-Wall -Wextra -pedantic -std=c++11 \
-g -g -o CMakeFiles/Snake.dir/src/main.cpp.o \
-c $HOME/Dev/sdl2-snake/src/main.cpp
私はあなたの代わりに裸なもののスマートポインタを使用することをお勧めします、とあなたは正しいかもしれないことを知っているが、ここで私はただ楽しんだし、見つけるために好奇心なぜそれがこのように壊れるのか。再現するのは難しいかもしれませんが(ビルドスクリプトはありますが)、目を覚ました経験豊富なC++開発者がすぐに問題を見つけるでしょう。
また、私は10年以上前に大学から何もやっていないので、コードレビューと改善の提案に感謝します。私のC++スキルはゼロに近いです。 (警告: - :
[/蛇/ tail_node.hpp含ま:13]> [:18 /蛇/ game_object.hppを含める]をorbitcowboyの先端に