SFML实现AVL树可视化程序运行报ntdll.dll 0xC0000005错误求助
错误原因
你遇到的0xC0000005访问冲突是典型的空指针解引用错误,写入地址0x00000004说明程序尝试对空指针偏移4字节的地址执行写入操作,触发崩溃的核心原因有两个:
- 第一:字体加载没有做合法性校验
代码中直接调用font.loadFromFile("CyrilicOld.TTF"),如果对应路径下不存在该字体文件,font对象就处于无效状态,后续draw函数中为sf::Text设置字体、计算文本边界时就会触发空指针访问。 - 第二:事件循环逻辑存在未定义行为
你的内层循环写为while (window.pollEvent(event) || change),当没有待处理事件但change为true时,event变量是未初始化的,此时直接访问event.type会读取垃圾值,甚至触发内存访问错误。
修复方案
1. 增加字体加载校验
修改main函数中的字体加载逻辑,加载失败直接抛出错误提示,避免后续使用无效字体:
// 替换你原来的font.loadFromFile行 if (!font.loadFromFile("CyrilicOld.TTF")) { // 也可以替换为系统自带字体路径,比如Windows下写"C:/Windows/Fonts/arial.ttf" std::cerr << "字体加载失败,请检查字体文件路径是否正确" << std::endl; return -1; }
2. 修正事件循环逻辑
把事件处理和页面刷新逻辑拆分,不要在无事件的时候访问未初始化的event:
while (window.isOpen()) { sf::Event event; while (window.pollEvent(event)) { // 所有和event相关的逻辑都移到这里面 if (event.type == Event::Closed || Keyboard::isKeyPressed(Keyboard::Escape)) { window.close(); } } float del_tim = clock.getElapsedTime().asMicroseconds(); del = del_tim / 4e4; clock.restart(); tim += del_tim; kadr++; if (tim > 1e6) { tim -= 1e6; kadr = 0; } // 持续按下的输入检测放在这里 if (Keyboard::isKeyPressed(Keyboard::Dash)) { view.zoom(1.03f); speed = speed * 1.03f; wid = wid * 1.03f; change = true; } if (Keyboard::isKeyPressed(Keyboard::Equal)) { view.zoom(0.97f); speed = speed * 0.97f; wid = wid * 0.97f; change = true; } if (Keyboard::isKeyPressed(Keyboard::Left)) { view.move(Vector2f(-speed * del, 0)); wid += speed * del; change = true; } if (Keyboard::isKeyPressed(Keyboard::Down)) { view.move(Vector2f(0, speed * del)); change = true; } if (Keyboard::isKeyPressed(Keyboard::Up)) { view.move(Vector2f(0, -speed * del)); change = true; } if (Keyboard::isKeyPressed(Keyboard::Right)) { view.move(Vector2f(speed * del, 0)); wid += speed * del; change = true; } if (Mouse::isButtonPressed(Mouse::Left)) { for (int i = 0; i < 10; i++) { int key = rand() - rand(); t = add(key, t); } change = true; } if (Keyboard::isKeyPressed(Keyboard::A)) { int key; cin >> key; t = add(key, t); change = true; } if (Keyboard::isKeyPressed(Keyboard::E)) { int key; cin >> key; t = erase(key, t); change = true; } if (Keyboard::isKeyPressed(Keyboard::N)) { view.zoom(wid_n / wid); speed *= wid_n / wid; wid = wid_n; } if (change) { window.setView(view); window.clear(Color(128, 106, 89)); if (t != nullptr) { // 空树的时候跳过渲染,避免多余调用 get_edg(t, 0, get_h(t)); wid_n = get(t, 0, get_h(t)); hei_n = get_h(t) * h_size; } window.display(); change = false; // 打开这行注释,避免无限刷新占用CPU } }
可选优化:修正AVL树插入逻辑
你当前的插入逻辑是把小于当前节点的值放到右子树,大于的放到左子树,和常规AVL树的实现相反,如果需要符合常规逻辑可以修改add函数的判断:
if (t->c > c) { t->l = add(c, t->l); // 原来写的t->r,改成t->l } else { t->r = add(c, t->r); // 原来写的t->l,改成t->r }
内容的提问来源于stack exchange,提问作者Bảo DG
相关产品推荐
相关产品推荐

