2017-11-17 21 views
-1

私は私の最初のchip8インタプリタとマルチスレッドプログラムの両方を書いて、この問題に遭遇しています:できるだけ早く私はスマッシングスタックはを検出し得るウィンドウを閉じて。私はしばらくの間、コードを検査してきましたが、私は問題を見つけることができません。本当に助けや助言が好きですか?スタックスマッシング:: RenderWindowの

emulator.hpp

#ifndef CHEAP8_SRC_EMULATOR_HPP 
#define CHEAP8_SRC_EMULATOR_HPP 

#include "chip8.hpp" 
#include "ui-settings.hpp" 

#include <SFML/Graphics.hpp> 

#include <atomic> 
#include <memory> 
#include <mutex> 
#include <string> 
#include <thread> 

#ifdef _WIN32 
#define OS_PATH_SEP '\\' 
#else 
#define OS_PATH_SEP '/' 
#endif 

class Emulator 
{ 
    //misc 
    const std::string gamePath; 
    const std::string gameTitle; 

    //emulator 
    unsigned char memory[chip8::kMemSize] = {0}; 

    //flags 
    bool gameLoaded = false; 
    std::atomic<bool> gameRunning{false}; 

    //ui 
    const double kPixelSize = 12.5; 
    std::shared_ptr<sf::RenderWindow> window; 
    const UiSettings uiSettings; 

    //threading 
    std::thread uiThread; 
    std::mutex mutex; 

    void loadGame(); 
    void loadFonts(); 
public: 
    explicit Emulator(char*); 
    ~Emulator(); 
    void run(); 
}; 

#endif //CHEAP8_SRC_EMULATOR_HPP 

emulator.cpp

#include "emulator.hpp" 

#include <chrono> //================ 
#include <fstream> 
#include <iostream> 
#include <iterator> 
#include <vector> 

void launchUi(std::shared_ptr<sf::RenderWindow> window, 
       const UiSettings& uiSettings, 
       std::atomic<bool>& gameRunning) 
{ 
    window = std::make_shared<sf::RenderWindow>(); 
    window->create(sf::VideoMode(uiSettings.width, uiSettings.height), 
        uiSettings.title, 
        sf::Style::Titlebar | sf::Style::Close); 
    window->setVerticalSyncEnabled(true); 
    window->setKeyRepeatEnabled(false); 
    const auto screenParams = sf::VideoMode::getDesktopMode(); 
    window->setPosition(sf::Vector2i(screenParams.width/2 - uiSettings.width/2, 
            screenParams.height/2 - uiSettings.height/2)); 

    sf::Event event; 
    while (window->isOpen()) { 
     while (window->pollEvent(event)) { 
      switch (event.type) { 
       case sf::Event::Closed: 
        window->close(); 
        gameRunning.store(false); 
       break; 

       default: 
       break; 
      } 
     } 
    } 
} 

Emulator::Emulator(char* path) 
    : gamePath(path), 
     gameTitle(gamePath.substr(gamePath.find_last_of(OS_PATH_SEP) + 1)), 
     uiSettings(kPixelSize, chip8::kScreenWidth, chip8::kScreenHeight, gameTitle), 
     uiThread(launchUi, window, std::ref(uiSettings), std::ref(gameRunning)) 
{ 
    loadGame(); 
    loadFonts(); 
} 

Emulator::~Emulator() 
{ 
    uiThread.join(); 
} 

void Emulator::loadGame() 
{ 
    std::ifstream file(gamePath, std::ios::binary); 
    if (!file.is_open()) { 
     std::cerr << "Couldn't open the game." << std::endl; 
     return; 
    } 

    std::vector<unsigned char> gameData; 
    gameData.insert(gameData.begin(), 
       std::istream_iterator<unsigned char>(file), 
       std::istream_iterator<unsigned char>()); 

    if (gameData.size() > chip8::kAllowedGameSize) { 
     std::cerr << "The game is too big to fit into memory." << std::endl; 
     return; 
    } 

    for (size_t i = 0; i < gameData.size(); ++i) { 
     memory[i + chip8::kMemStart] = gameData[i]; 
    } 

    gameLoaded = true; 
    std::cout << "Game loaded. Size: " << gameData.size() << '\n'; 
} 

void Emulator::loadFonts() 
{ 
    for (int i = 0; i < chip8::kFontsetSize; ++i) { 
     memory[i] = chip8::kFontset[i]; 
    } 
    std::cout << "Fontset loaded." << '\n'; 
} 

void Emulator::run() 
{ 
    if (!gameLoaded) { 
     return; 
    } 

    gameRunning.store(true); 
    while (gameRunning.load()) { 
     std::this_thread::sleep_for(std::chrono::milliseconds(100)); 
    } 
} 

EDIT:

#include "emulator.hpp" 

#include <iostream> 

int main(int argc, char *argv[]) 
{ 
    if (argc != 2) { 
     std::cerr << "Usage: ./" << OS_PATH_SEP << "cheap8 game." << std::endl; 
     return 1; 
    } 

    Emulator emu(argv[1]); 
    emu.run(); 

    return 0; 
} 
+0

main関数には何が含まれていますか? – M4rc

+0

@ M4rcを元の投稿に追加しました – vdublevsky

答えて

1

Emulatorのあなたのインスタンスは、それは、スタック領域を使用しますので、スタック上に作成されていますすべてのメンバ変数を格納するのに十分です。

この1つはかなり大きいです:

unsigned char memory[chip8::kMemSize] = {0}; 

それが唯一のメタデータ(サイズ、データへのポインタ)が含まれ、ヒープとクラスインスタンスにデータを格納するように、あなたはstd::vectorにそれを変更することがあります。

また、memory配列への範囲外アクセスの影響を変更します。スタックを使いこなし、返信アドレスなどの変更を行う代わりに、純粋なデータオブジェクトに対して破損が行われます。

境界外アクセスがないように、ベクトルのat()メンバ関数を使用できます。

+0

chip8 :: kMemSizeは4KBです。これは、「標準的な」CHIP-8 VMの要件の1つです。私はそれが本当にたくさんの記憶だとは思わない。 – vdublevsky

関連する問題