湖北武汉医院网站建设关键词优化快速
0x00前言
最近有一次在checkout之后,出现一次异常的程序运行,在成功完成编译时出现了异于原本逻辑的动作,因为这种情况可遇不可求,所以现在在这里记录一下,以备日后回溯。
阅读本文,您可能需要掌握的知识:
技能 | 熟练度 |
---|---|
git | 熟悉 |
编译器 | 了解 |
0x10 环境
本人使用的环境时IAR,使用git相关的版本控制程序。这里是前提
0x20 缘由
在某一次我在成功使用git checkout其他分支并且进行部分合并操作时,当前的版本管理器报错提示我当前的文件内部有部分冲突。
我修补完成全部的冲突。并且进行了完成后的一次编译。以保证在语法层面上没有什么错误。
编译成功,我没有对此有太多的关注。并且更新到机器。
机器似乎正常工作,于是我将机器给了硬件大佬。但是不过多久,硬件大佬找到我说“这个机器某个功能的参数似乎总是莫名其妙的显示,你要不要过来看下”
我过去后,发现某个功能莫名其妙的被设置了,但是我在更新时根本没有修改过这端代码。暂时陷入了僵局。
幸好我还有在线调试的解决方式
我将调试器接入当前芯片。我进行了长时间的调试,最后终于定义到了问题。是因为不可能写入操作的位置被强行写了一部分错误的参数。型号大部分错误的位置都是暂时不需要使用的参数,所以这种灾难性的错误覆写竟然还能让机器正常工作🙂
随后通过汇编语言发现,当前的寻址是奇怪的位置,以至于我完全不知道当前的寻址基地址从哪里来的。随后进行一通分析,发现现在的编译中间文件出现问题,随后我就rebuild解决了这个问题。
0x30 分析
因为当前的make系列都是具有时间戳的方式进行检查当前文件是否需要更新,而如果原本修改了一个文件,又因为某些原因恢复到之前的状态时,有些实现的编译文件的及地址就会有很大的偏差。这样就会出现很大的区别。
举个例子来说:
现在有两个文件
///main.c
int test[];void main()
{test[200] = 200;
}///test.c
extern int test[256];void test()
{test[256] = 200;
}
现在被编译成了obj类文件。而且现在的时间点在2021年7月8日21点34分.
因为某些原因,文件被恢复成了这样:
///main.c
int test[];void main()
{test[200] = 200;
}///test.c
extern int test[200];void test()
{test[200] = 200;
}
时间点在2020年7月7日21点34分.
这时如果使用make时,当前的文件obj较c文件与之前的所有的头文件都要新或者是时间持平。这样就会出现当前的文件没办法实时更新的情况。这样也会带来不可预料的危险。
0x40 解决方案
知道了具体的原因,解决的方法也就简单粗暴了。我能想到很多解决的方案:
- 在每次checkout时使用hook切换当前的obj文件夹,保证每次checkout都会重新检出当前的参数
- 使用脚本每5秒计算当前文件的crc。保证在算力允许的情况下,更新当前的obj。如果出现与之前不同的crc则重新保存一边文件,以更新时间戳保证当前的make文件可以正常识别。
判断的情况下,我选择了第一个解决方案,因为从时间和效率来讲都是较为简单的。也比较方便移植。而牺牲就是全部都要重新编译。如果是大型的项目可能需要十分长的编译时间。第二个解决方案,则将绝大多数的时间分散到平时的时间计算。最后的每次更新反倒是节省时间。可以保证大型项目的更新。但是编写脚本和维护也需要很长时间,所以我准备后期什么时候有空了再开这种坑。
0x50 实现
第一种解决方式主要依赖git hook功能,git在很多关键操作下做了一些较为统一的钩子实现接口,通过执行返回确认是否可以提交。我们这里所使用的就是pre-checkout的接口。这个接口就是在checkout执行阶段之后。这时git会自动运行.git\git_hook\pre-checkout
文件,这个文件可以写成一个脚本文件,这样就可以直接删掉了。
#!/bin/shrm -rf YOUR_DIR
这里的目录需要仔细确认,否则也会出现不可预料的情况。
0x60 更多
本文首发自 记:关于异常的checkout导致了错误的显示清除,更多文章可进入我的博客详查。