You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SFML/C++从vector绘制文本触发访问违例错误求助

解决SFML中sf::Text绘制时的访问违例错误

问题根源

你遇到的0xC0000005访问违例,核心原因是sf::Text对象仅持有指向sf::Font的指针,而非直接存储字体数据。在GetAllTextOptions函数中,你通过值传递传入sf::Font font,这会生成一个字体的局部副本。当函数执行完毕返回时,这个局部font对象会被销毁,导致所有生成的sf::Text对象中的字体指针变成悬垂指针——后续调用window.draw时,SFML会尝试访问已被释放的内存地址,最终触发错误。

解决方案

1. 传递sf::Font的引用而非值

修改GetAllTextOptions的参数为引用类型,避免创建局部字体副本,确保sf::Text持有的指针指向全局/主作用域中有效的字体对象:

std::vector<sf::Text> Menu::GetAllTextOptions(TextHandler& handler, sf::Font& font) {
    std::vector<TextDocument>* all_available_documents = handler.GetTextDocuments();
    std::vector<sf::Text> menu_text_options;

    for (int i = 0; i < all_available_documents->size(); i++) {
        sf::Text text;
        text.setFont(font);
        // 移除多余的'\n':sf::Text默认不支持自动换行,直接加'\n'会显示为未知字符
        text.setString(std::to_string(i) + ") " + all_available_documents->at(i).GetDocumentName());
        menu_text_options.push_back(text);
    }
    return menu_text_options;   
}

2. 保证字体对象的生命周期有效性

在主程序中创建的sf::Font实例,必须在所有使用它的sf::Text对象被销毁前保持存在。建议将sf::Font声明为:

  • 类的成员变量(比如Menu类的成员)
  • 主循环所在作用域的局部变量
  • 全局变量(不推荐,但能快速验证)

避免在临时作用域中创建字体,防止其提前被销毁。

3. 优化绘制函数(可选)

使用C++范围for循环简化遍历逻辑,同时提升代码可读性:

void Menu::DrawAllOptions(sf::RenderWindow& window, std::vector<sf::Text>& menu_text_options) {
    std::cout << menu_text_options.size() << " is the current size " << std::endl;
    try {
        // 范围for循环遍历所有文本对象
        for (auto& text_option : menu_text_options) {
            window.draw(text_option);
        }
    }
    catch (const std::exception& ex) {
        std::cout << "Exception: " << ex.what() << '\n';
    }
} 

额外注意事项

sf::Text默认不支持自动换行,直接在字符串中添加'\n'不会触发换行,反而会显示为方块状的未知字符。如果需要实现换行效果,需先设置字符大小,再通过text.setString传入包含'\n'的字符串,并可调用text.setLineSpacing()调整行间距。

内容的提问来源于stack exchange,提问作者MontyVan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 01:01:23