本帖最后由 zhifu3158 于 2022-4-27 15:32 编辑
【备忘】记录一次:软件崩溃,故障模块名称:ntdll.dll 的处理办法
前言: 软件崩溃的原因有多种多样,技术解说和解决办法也很多,这里仅记录一次 我遇到的软件崩溃的解决过程,(本人小白一枚,个人想法,如有不对或欠佳之处望大家不吝告知)
事件原因:在写一个多线程采集软件时,发现软件运行一段时间后很容易出现崩溃的情况,提示故障模块名称:ntdll.dll 异常代码:c00000fd ....
解决过程如下:
1.先看 “异常代码”
异常代码:c00000fd 度娘搜索说是内存问题,可能出现的地方有:数组操作、传参、栈内存(基本就是这个)...
针对易语言进一步思考如下:
数组操作:若数组下标、数组类型等出差易语言会给出详细的错误信息,而且在传参时数组默认是传指针方式,故此问题可以排除。
传参: 易语言会针对 文本、数组、自定义类型等变量默认为指针方式(整数、小数、逻辑性等基础类型才需要开发人员注意),开发者无需特别关注,(易语言这点很智能的),所以该问题可以排除。
栈内存:栈内存操作,易语言很少涉及啊(主要是编译器在编译过程中已经处理好了各种涉及栈内存的操作,开发人员却很少用到相关命令),但是可以确定是这里出现了问题,因为用多少,相关知识储备的也少,也就越容易出错。
这里要考虑到易语言中可能出现的操作栈内存的地方:变量指针 上面说到了传参中数组和文本默认是传指针的,多线程也是只支持整数型(精易模块支持文本型的也是转成指针操作),而整数型变量就是存放在栈内存中的,可以大体理解为指针操作就是栈内存操作,那问题就找到了!!!
既然知道了:指针操作 ≈ 栈内存操作 而我的程序中使用了多线程,其中传参是 文本型变量指针(取指针地址_文本型),线程内接收到指针数据后再取得文本数据(指针_到文本) ,那就调试测试下:
将线程中等到的文本数据(指针_到文本) 调试出来查看,启动线程100,结果有十多个变量提示为 空 ! 为空!!!!!使用其他的变量指针操作的命令都是会有一定数量为空!那问题就出现在这里了。
继续分析为什么会出现取指针变量结果为空的情况:【可能出现错误的情况】
1.传给多线程的变量为 局变量,在调用多线程的子程序结束后 里面的局变量会被销毁,若这个时候多线程还在操作这个变量就会出错!
2.多线程在取指针变量(指针_到文本)时未加许可证,导致提示操作相同变量而出错(仅仅是读取理论上不会出错的啊)
3.变量指针操作的命令有BUG(理论上不会)
- - - 因为储备的栈内存操作的知识量太少,到底是哪里出现了问题以及针对栈内存操作的解决办法并不是很了解,但是纵观上面三种情况都有个共同点:多线程同时操作一个相同变量 既然我不懂栈内存,那我就不让多线程操作相同的变量。
解决办法: 使用鱼刺多线程中的 :“_写内存文本”命令,虽然也是返回一个变量指针(内存地址),但是他的操作方式与易语言自带命令不同,易语言和精易模板是取这个变量的指针地址,而鱼刺的命令是“复制该变量的数据内容然后放在内存中并返回该地址”,也就是一个新的变量的指针地址(即使原先的变量销毁了也没事),仅仅是拷贝了一份数据,返回的事拷贝后的变量指针地址,在 _读内存文本 时会默认释放内存 这里释放的是拷贝后的变量内存而不是原始变量。
总结:易语言和精易模块中的 取变量指针 是操作原始变量,而鱼刺中的 _写内存文本 是拷贝一份后的变量。
***** 修改后软件再无崩溃情况!! ****
【注】:这里的“变量指针地址”的说法并不准确,只是为了大家方面理解而已,(具体的是:存放在栈内存中的一组整数数据,而该数据指向了一个变量在堆内存中(文本是放在堆内存中的)所在的位置。 而所谓的:变量指针、内存指针、变量指针位置、内存位置等仅仅是不同的叫法,在宏观上是相同的意思,如果要细分指针和地址又不一样了,因为存放在栈内存中的数据不仅包含对应变量的内存地址,还包含其大小长度等数据。。这里不多说了不然又要迷糊了。。)
总结:出现崩溃后先搜索 异常代码 大体的了解下出错问题,然后针对易语言的特性进行逐个排查,对于指针操作要注意的地方不仅仅是多线程,还要考虑 DLL 的调用,考虑同时操作变量、局变量等因素。。。欢迎大家指正错误之处并请求大家也说下自己针对各种可能出现的错误的解决办法和理解!!
|