Summary¶
- 崩溃:大多是因为指针未判空(注意崩溃信号SEGV_MAPERR@一般后跟小地址),另是野指针(即未进行初始化的指针),再者某些os针对abort信号的处理是崩溃该进程
- 内存泄露:存在死锁(多个锁顺序问题导致交叉死锁);某一流程失败后未进行处理导致后续操作无法正常进行(内源性触发错误处理)
- memcpy崩溃:传入的size过大(不匹配问题),可使用memcpy_s,写明要拷贝的size和容量size
- 可重入逻辑要 瞻前顾后,某一状态完成后,若是最终状态,则应拒绝其他任何前置状态的处理。
- unique_ptr使用注意:release()是切断智能指针与被管理对象的关系,会返回指针,需要程序自己对返回的指针指向的对象进行管理; 调用release后智能指针声明周期到了之后,对象不被析构。release()内部实现是调用get()返回裸指针
- shared_ptr 交叉指引,类中包含且被包含的有shared_from_this()
- shared_from_this的使用不能在构造函数里,因为对应的weak_ptr还没创建
- map不要在遍历时erase,除非每次使用erase的返回值更新迭代器
- ffmpeg拆MP4里的h264帧需要加上帧头信息;音频处理注意通道设置
- 类析构函数里应且必须对该类管理的指针对象进行显式释放
- 崩溃在入类析构函数,考虑类内成员的释放(智能指针管理的对象是否释放)
- c++报错
error: member access into incomplete type
,未加头文件哈哈哈 -
c++出现new崩溃/delete崩溃,即正常的new/delete崩溃,且可用内存很富余,崩溃点乱七八糟(诸如SIGBUS(BUF_ADRERR), SIGILL(ILL_ILLOPC) , SIGSEGV等的崩溃信息),可以考虑是堆内存越界操作导致堆内存被破坏,引起后续的new/delete崩溃(因为系统在分配堆内存时,会在给用户的堆内存块头部 和尾部增加一些头尾信息,用于管理堆内存,若被越界操作修改,会导致后续的new/delete崩溃。)
- new崩溃或者抛出异常,除了内存不够,堆内存越界操作被破坏,还有种可能是进程中的内存碎片过多,导致后续如果申请大内存会失败
- 堆内存越界操作排查方向:对于音视频领域,存在编解码相关的,包括输入和输出buffer的申请与管理,考虑是否是输出buffer设置太小 (一般是通过计算得出来的,可能是没考虑sizeof(INT_PCM)等这种因子导致输出buffer大小小了一倍,导致解码器输出后在写buffer时越界写堆内存,引起后续的崩溃)
- 遇到的是代码开发者引入的fdk_aac第三方库的使用错误问题,针对这种音视频领域的第三方库,特别是移动端的可能ffmpeg都有使用这些第三方 库的示例代码,排查时可以进行参考。
-
崩溃到系统提供的动态库,考虑是否是自建的类生存空间的问题,如napi的callback类对象被析构了,但还有地方要调用其中的静态成员函数,以及检查 使用系统库的api接口的版本,是否过时。
- 个人编码坚持:函数签名很重要,特别是返回值,充分利用返回值,有返回值就一定要用上,不用就返回空。接手别人代码调试时出问题多考虑异常返回值 是否真正被正确处理了。
-
sigsegv空指针崩溃,stl库的函数调用崩溃,但崩溃栈顶指向的是该函数的库实现代码,而不是调用方的地方,实则是调用方的空指针问题,而不是库函数实现的问 题(很无语啊,,明明是GetBufferList()返回的一个list引用为null,但调用list的size方法时崩溃,栈顶指向的时list的size函数实现代码。,,。好误导,,)
通过查看汇编代码,如果调用的某对象的函数的返回值是一个引用,则只会对该对象的地址所指向的空间(若对象未null,则指向的空间通常为0x00)进行加0x10操作 这也就是为什么崩溃栈显示的SIGSEGV后面的MAPERR地址显示的是0x00000010 但如果没有对该返回的引用进行使用,则是不会取解析加出来的0x00000010,也不会崩溃,只有实际使用才会崩溃(这时才会进行访问内存) 而返回值不是引用的对象,立马崩溃,是因为它对计算出来的地址进行了访问
-
创建的线程如果不join也不detach的话,在thread的析构函数中会执行std::terminate(),这样会直接abort,部分os操作是使当前进程崩溃。