当前位置: 首页 > news >正文

kicad运行时出错,_Pnext->_Myproxy = nullptr;访问内存出错

花费了比较长的时间,解决了编译过程中遇到的许多问题后,终于把这个开源的工程编译好了,运行post build 脚本将需要的链接文件拷贝好。正当我以为没有任何问题了,双击可执行程序运行。

结果运行起来的时候报错了,提示无法正常启动,根据这个这个报错的提示,网上搜了一下,都说是缺少dll库导致的,于是将post build脚本又运行了一遍,重新双击打开可执行程序,还是报一样的错。

那么是缺少那个dll库导致的呢?于是我打开系统的事件查看器,从里面找到了应用程序错误事件,点击看到了详细信息,从描述来看出错的模块是libprotobufd.dll,是在运行这个dll的过程中出现的异常,并非缺少dll导致。

{// Use IntelliSense to learn about possible attributes.// Hover to view descriptions of existing attributes.// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387"version": "0.2.0","configurations": [{"name": "(msvc) launch","type": "cppvsdbg","request": "launch","program": "D:\\Kicad\\kicad-source-mirror\\build\\out\\bin\\kicad.exe"}]
}

为了进一步弄清楚这个库出错的原因和位置,于是在vscode编辑器中将C/C++相关的插件安装上,设置好debug条件,运行debug功能后,跳转到了出现异常的代码位置。

从给的错误信息可以看出来_Pnext是一个非法值,那么这个值为什么是一个非法值,目前猜测它是一个空指针,或者指向的内存不对,目前只是有这样一个概念,带着这样的疑惑继续分析原因。

_EXPORT_STD template <class _Ty, class _Other = _Ty>
_CONSTEXPR20 _Ty exchange(_Ty& _Val, _Other&& _New_val)noexcept(conjunction_v<is_nothrow_move_constructible<_Ty>, is_nothrow_assignable<_Ty&, _Other>>) {// assign _New_val to _Val, return previous _Val_Ty _Old_val = static_cast<_Ty&&>(_Val);_Val         = static_cast<_Other&&>(_New_val);return _Old_val;
}

exchange的作用是将第一个参数设置成第二个参数的值,然后返回第一个参数的值,所以auto _Pnext = _STD exchange(_Myproxy->_Myfirstiter, nullptr)可以理解为:

_Pnext = _Myproxy->_Myfirstiter;

_Myproxy->_Myfirstiter = nullptr;

上述只是简单理解这个函数的功能,这样看这里也没有问题

到了这里我们还是无法知道_Pnext指向的区域为什么变成非法的,还有就是_Pnext到底指向的是什么,也就是它到底是什么,怎么来的,于是根据发生异常的调用栈进一步追踪,看一下具体是怎么发生的。根据调用栈我们看到了一个明显的可能有问题的地方那就是std::string::~basic_string(),这里先猜测string对象析构的时候发生了异常,析构的时候一般会去释放资源,是不是释放的资源出来问题,所以才导致的异常。

bool EncodedDescriptorDatabase::DescriptorIndex::AddSymbol(absl::string_view symbol) {SymbolEntry entry = {static_cast<int>(all_values_.size() - 1),EncodeString(symbol)};std::string entry_as_string = entry.AsString(*this);// We need to make sure not to violate our map invariant.// If the symbol name is invalid it could break our lookup algorithm (which// relies on the fact that '.' sorts before all other characters that are// valid in symbol names).if (!ValidateSymbolName(symbol)) {ABSL_LOG(ERROR) << "Invalid symbol name: " << entry_as_string;return false;}auto iter = FindLastLessOrEqual(&by_symbol_, entry);if (!CheckForMutualSubsymbols(entry_as_string, &iter, by_symbol_.end(),*this)) {return false;}// Same, but on by_symbol_flat_auto flat_iter =FindLastLessOrEqual(&by_symbol_flat_, entry, by_symbol_.key_comp());if (!CheckForMutualSubsymbols(entry_as_string, &flat_iter,by_symbol_flat_.end(), *this)) {return false;}// OK, no conflicts.// Insert the new symbol using the iterator as a hint, the new entry will// appear immediately before the one the iterator is pointing at.by_symbol_.insert(iter, entry);return true;
}

于是继续追踪代码里面是哪个执行造成的,还是根据前面的调用栈,我们看到执行完AddSymbol后,会调用~basic_string(),那么根据上面的代码来看,应该是entry_as_string这个对象的使用有问题。

根据debug信息,看到entry_as_string的内存有问题,到这来还不知道是因为被释放了,还是本身创建出来的就有问题,继续追踪这个是怎么创建出来的。

std::string AsString(const DescriptorIndex& index) const {auto p = package(index);return absl::StrCat(p, p.empty() ? "" : ".", symbol(index));}
std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c) {std::string result;// Use uint64_t to prevent size_t overflow. We assume it is not possible for// in memory strings to overflow a uint64_t.constexpr uint64_t kMaxSize = uint64_t{std::numeric_limits<size_t>::max()};const uint64_t result_size = static_cast<uint64_t>(a.size()) +static_cast<uint64_t>(b.size()) +static_cast<uint64_t>(c.size());ABSL_INTERNAL_CHECK(result_size <= kMaxSize, "size_t overflow");strings_internal::STLStringResizeUninitialized(&result, static_cast<size_t>(result_size));char* const begin = &result[0];char* out = begin;out = Append(out, a);out = Append(out, b);out = Append(out, c);assert(out == begin + result.size());return result;
}

这里重点是std::string result;这个result有问题,但是有实在看不出代码哪里有问题,于是只能继续debug,进入这个函数后一步步运行,看一下具体是哪里出了问题。

在运行的过程中,这个result的就没有显示出来,它的内存是什么,指向哪里根本不知道。

只知道这个函数返回的时候,entry_as_string指向了一个错误的内存,最终导致崩溃,目前从debug的过程来看不出具体是什么原因导致的问题。

于是写了一段类似的测试代码,看看能不能复现到这样的问题,也可以对比这个过程中有哪些不一样,看看能不能找出根本原因。

测试代码在运行的过程中没有出错,只能看到它们不一样的地方

异常代码测试代码
1std::string result 没有跑构造函数std::string result 正常跑构造函数
2debug过程没有显示result的信息debug过程会显示result的信息
3函数里面的begin、out等变量也没有信息函数里面的begin指向和显示没有问题

目前猜测可能是std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c) 函数里面的代码被优化了导致的。

http://www.xdnf.cn/news/1046827.html

相关文章:

  • Spring Boot Web开发
  • 《拖延心理学》:深度剖析与应对指南​
  • 深入解析解释器模式:语言解析的优雅实现
  • Leetcode 刷题记录 16 —— 栈
  • 【git】 `git rm --cached *.pt` 删除了缓存,但这些大文件的历史记录仍然存在于Git历史
  • 《棒球百科》棒球怎么玩·棒球9号位
  • 岐黄慧问六月最终项目完成情况
  • 用于汽车毫米波雷达的四维高分辨率点云图像
  • 微软Bing正式推出AI视频生成工具:Bing Video Creator,由Sora技术驱动,限时免费体验!
  • 机器学习实验报告5-K-means 算法
  • ansible变量
  • 如何修改PyCharm的界面颜色(超详细)
  • vue2和vue3的底层逻辑原理、区别、用法以及应用优缺点
  • 大模型训练与推理显卡全指南:从硬件选型到性能优化
  • 软考 系统架构设计师系列知识点之杂项集萃(90)
  • AOP +ThreadLocal实现对接口监控
  • linux设置信号量系统参数
  • 【Dify系列】【Dify 核心功能】【应用类型】【三】【Agent】
  • Python 面向对象编程基础-类的创建与__init__实例化
  • [Java 基础]正则表达式
  • 第10章:Neo4j与其他技术集成
  • 图数据库neo4j部分用法浅讲
  • 基于SpringBoot和Leaflet的电影票房时序展示-以《哪吒2》为例
  • 6,TCP客户端
  • 【系统设计【3】】系统设计面试框架:从理论到实践的完整指南
  • 2013-2023年 地级市-财政透明度数据-社科经管实证数据
  • 使用Netlify进行简单部署
  • UE5 仿 鸣潮人物渲染
  • 【项目实训】【项目博客#09】HarmonySmartCodingSystem系统后端智能API检索与代码助手实现(6.2-6.15)
  • Kafka代码模板