我正在为 NES 编写一个简单的模拟器。我正在尝试将 SDL2 用于图形,并使用 ImGui (SDL 渲染器,不一定限于它)。
这一切都适用于 github 上的相应示例,直到我进行了一些重构并移动了与其自己的类相关的所有图形。
现在程序无法启动,并在 ImGui_ImplSDLRenderer2_Init(renderer);
上抛出
SIGILL 错误(代码 -1073741795)。如果我将其注释掉,则错误会在其前面抛出一行,即
ImGui_ImplSDL2_InitForSDLRenderer(window, renderer);
。
调试错误表明,当两个函数之一尝试调用
ImGui::GetIO()
时,会发生错误。我尝试了一切,但似乎没有任何效果。
这是我的代码。
图形.h
#include "imgui.h"
#include "imgui_memory_editor.h"
#include "imgui_impl_sdl2.h"
#include "imgui_impl_sdlrenderer2.h"
#include <SDL.h>
struct WindowSettings {
explicit WindowSettings(const char *title, int width, int height, bool use_default = true);
SDL_WindowFlags window_flags;
SDL_RendererFlags renderer_flags;
ImGuiConfigFlags_ imgui_flags;
int width, height;
const char* title;
};
class Window {
public:
Window(WindowSettings *settings);
~Window();
int init();
void quit();
bool poll_events();
bool should_close() { return event.type == SDL_QUIT || (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window)); }
void start_imgui_frame();
void render();
void set_background_color(float r, float g, float b, float a) { background = {r, g, b, a}; }
private:
WindowSettings *settings;
SDL_Window *window;
SDL_Renderer *renderer;
ImGuiIO *io;
SDL_Event event;
ImVec4 background = {58, 58, 77, 255};
};
图形.cpp
#include "Graphics.h"
WindowSettings::WindowSettings(const char *title, int width, int height, bool use_default) {
this->title = title;
this->width = width;
this->height = height;
if (!use_default) return;
window_flags = (SDL_WindowFlags)(SDL_WINDOW_ALLOW_HIGHDPI);
renderer_flags = (SDL_RendererFlags)(SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
imgui_flags = ImGuiConfigFlags_NavEnableKeyboard;
}
Window::Window(WindowSettings *settings) {
this->settings = settings;
window = nullptr;
renderer = nullptr;
}
Window::~Window() {
quit();
}
void Window::quit() {
ImGui_ImplSDLRenderer2_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
int Window::init() {
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) {
printf("Error: %s\n", SDL_GetError());
return -1;
}
window = SDL_CreateWindow(settings->title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, settings->width, settings->height, settings->window_flags);
if (window == nullptr) {
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return -1;
}
renderer = SDL_CreateRenderer(window, -1, settings->renderer_flags);
if (renderer == nullptr) {
SDL_Log("Error creating SDL_Renderer!");
return 0;
}
SDL_RendererInfo info;
SDL_GetRendererInfo(renderer, &info);
SDL_Log("Current SDL_Renderer: %s", info.name);
IMGUI_CHECKVERSION();
ImGui::CreateContext();
io = &ImGui::GetIO(); (void)io;
io->ConfigFlags |= settings->imgui_flags;
ImGui::StyleColorsDark();
ImGui_ImplSDL2_InitForSDLRenderer(window, renderer);
ImGui_ImplSDLRenderer2_Init(renderer); // Error line
}
bool Window::poll_events() {
if (SDL_PollEvent(&event)) {
ImGui_ImplSDL2_ProcessEvent(&event);
return true;
}
return false;
}
void Window::start_imgui_frame() { // NOLINT(*-convert-member-functions-to-static)
ImGui_ImplSDLRenderer2_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
}
void Window::render() {
ImGui::Render();
SDL_RenderSetScale(renderer, io->DisplayFramebufferScale.x, io->DisplayFramebufferScale.y);
SDL_SetRenderDrawColor(renderer, (Uint8)background.x, (Uint8)background.y, (Uint8)background.z, (Uint8)background.w);
SDL_RenderClear(renderer);
ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData(), renderer);
SDL_RenderPresent(renderer);
}
main.cpp
#include "imgui.h"
#include "imgui_memory_editor.h"
#include "imgui_impl_sdl2.h"
#include "imgui_impl_sdlrenderer2.h"
#include <SDL.h>
#include "Cpu.h"
#include "Graphics.h"
int main(int, char**)
{
WindowSettings settings("NesMu - alpha1.0.0", 800, 800);
Window *win = new Window(&settings);
win->init();
uint8_t program[] = {0XA9, 0XC0, 0XAA, 0XE8, 0X00};
CPU cpu;
cpu.set_demo(program);
bool end = false;
static MemoryEditor prog_editor;
prog_editor.ReadOnly = true;
// Main loop
bool done = false;
while (!done)
{
while (win->poll_events())
{
if (win->should_close()) done = true;
}
win->start_imgui_frame();
{
ImGui::Begin("CPU Registers");
ImGui::Text("PC: %04X", cpu.getPC());
ImGui::Text("A: %02X", cpu.getA());
ImGui::Text("X: %02X", cpu.getX());
ImGui::Text("Y: %02X", cpu.getY());
ImGui::Text("SP: %02X", cpu.getSP());
ImGui::Text("Flags: %08p", cpu.getFlags());
if (ImGui::Button("Step", {60, 20}) && !end) end = cpu.step();
ImGui::SameLine();
if (ImGui::Button("Reset", {60, 20})) { cpu.reset(); end = false; }
ImGui::End();
}
strcpy(reinterpret_cast<char *>(program), reinterpret_cast<const char *>(cpu.getDemo()));
prog_editor.DrawWindow("Program memory", program, sizeof(program));
prog_editor.GotoAddrAndHighlight(cpu.getPC(), cpu.getPC() + 1);
win->render();
}
win->quit();
return 0;
}
有人可以帮助我吗?
编辑1 这里要求的是汇编指令和完整的调用堆栈。 这似乎是指令:
ud2
根据调用堆栈,Clion 只让我检索当前线程的堆栈。在这里:
Window::init Graphics.cpp:67
SDL_main main.cpp:15
解决方案:
当我决定在 Clion 中设置 WSL 工具链后,C++ 编译器警告我在 Window::init()
函数中存在
缺少 return 语句。
在最后添加了声明,一切又开始按预期进行。
我仍然不知道为什么 g++ 和 gcc 都没有警告我这一点。
感谢所有试图帮助我的人。