【问题标题】:Exception 0x00000004 (sfml-graphics-2.dll) occuring after compilation编译后出现异常 0x00000004 (sfml-graphics-2.dll)
【发布时间】:2020-07-21 14:26:28
【问题描述】:

最近,我开始学习 SFML。我想做的第一件事是一个简单的菜单——所以我为所有菜单创建了一个界面,包含受保护字段中其他菜单所需的一切。但是,我的代码有时会引发异常,我不知道为什么。

#include <SFML/Graphics.hpp>
#include <iostream>

class Menu
{
protected:
    sf::Color red;
    sf::Color white;
    std::vector<sf::Text> displayedText;
    int currentOption{ 0 };
public:
    virtual void draww(sf::RenderWindow& window) = 0;
    virtual void clickButton() = 0;
    virtual void moveUp() = 0;
    virtual void moveDown() = 0;
};

class FirstMenu : public Menu
{
public:
    FirstMenu(sf::RenderWindow& window)
    {
        sf::Text text;
        sf::Font font;
        if (!font.loadFromFile("arial.ttf"))
        {
            std::cout << "Font error. \n";
        }
        text.setFont(font);
        text.setString("Play");
        displayedText.push_back(text);
        text.setString("Options");
        displayedText.push_back(text);
        displayedText[0].setFillColor(red);
        displayedText[0].setPosition(20, 30);
        displayedText[1].setPosition(30, 30);
    }
    virtual void clickButton()
    {
        switch (currentOption)
        {
        case 0:
            std::cout << "Playing. \n";
            break;
        case 1:
            std::cout << "Options. \n";
            break;
        }
    }
    virtual void moveUp()
    {
        currentOption++;
        displayedText[currentOption].setFillColor(white);
        for (int i = 0; i < displayedText.size(); i++)
        {
            if (i == currentOption)
            {
                displayedText[i].setFillColor(red);
            }
        }
    }
    virtual void moveDown()
    {
        currentOption--;
        displayedText[currentOption].setFillColor(white);
        for (int i = 0; i < displayedText.size(); i++)
        {
            if (i == currentOption)
            {
                displayedText[i].setFillColor(red);
            }
        }
    }
    virtual void draww(sf::RenderWindow& window)
    {
        if (!displayedText.empty())
        {
            for (int i = 0; i < displayedText.size(); i++)
            {
                window.draw(displayedText[i]); //Exception thrown here
            }
        }
    }
};

int main()
{
    sf::RenderWindow window(sf::VideoMode(500, 500), "SFML works!");
    FirstMenu menu(window);
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }
        window.clear();
        menu.draww(window);
        window.display();
    }
    return 0;
}

抛出异常时显示的文本是: “位置 0x799B35BB (sfml-graphics-2.dll) 中未处理的异常 0xC0000005: 读取位置 0x00000004" 时访问冲突

【问题讨论】:

  • 该错误意味着您正在访问超出范围的数组。你能调试你的程序吗?我已经看到了一些我会仔细检查的事情:1)我会在 window.close() 之后跳出 while 循环,2)我会在 FirstMenu 构造函数中使用两个 sf::Text 变量,以及 3)我将检查currentOption 以不超出displayedText 向量边界(即++ 不能上升size()-1 和-- 不能下降0。
  • 尝试auto 与向量后仍然抛出异常。调试时抛出异常。
  • 您是如何构建可执行文件和链接 sfml DLL 的?
  • 我在 Visual Studio 中使用“Debug x86”选项来调试我的代码。我将所有库链接到“Release”和“Debug”(在 Debug 中,我添加了“-d”后缀)。我完全不知道为什么我的程序会抛出这个异常
  • 我的代码写得好吗?我不知道是我犯了错误还是将 SFML 链接到 Visual Studio 2019 时出现问题

标签: c++ exception sfml


【解决方案1】:

我能看到的主要问题是在FirstMenu 的构造函数中你是

sf::Font font;
if (!font.loadFromFile("arial.ttf"))
{
    std::cout << "Font error. \n";
}
text.setFont(font)

本质上是将文本的字体设置为本地字体对象。这是有问题的,因为 SFML 中的文本不会复制传入的字体资源。

SFML 关于 text 类的文档说明了这一点关于 setFont

字体参数是指一种字体,它必须与文本一样长 使用它。实际上,文本不会存储自己的字体副本,而是 而是保留一个指向您传递给此函数的指针。如果 字体被破坏并且文本尝试使用它,行为是 未定义。

还值得注意的是,Shapes 和 Sprites 的 setTexture 函数的行为类似,因为它不存储纹理资源的副本。

修复方法是确保字体对象在被文本对象使用时不会被破坏。

最简单的修复包括:

  1. 在 main 中加载字体并将字体传递给需要它的函数和对象。
  2. 如果您使用的是单一字体,那么有一个全局函数,该函数具有静态字体并且只构造和加载一次。
  3. 如果需要多种字体并且您不想传递字体,那么您可以为字体使用单例资源管理器。

【讨论】:

    猜你喜欢
    • 2015-09-01
    • 2015-07-26
    • 1970-01-01
    • 1970-01-01
    • 2018-10-28
    • 2015-05-28
    • 2015-02-16
    • 2011-06-11
    • 2010-10-22
    相关资源
    最近更新 更多