# 做一道练习,设计思想是在双向链表中存指针而非存值,因而可以在运行时动态决定指针所存的类型。
# 之前做此练习测试没有Bug,本次练习要为指针加上线程和锁,然而在测试时出错。并且报错地点在334行,远离了后来定位出来的311行。
# 刚开始调试是把线程测试函数注释掉,仅调试单线程版,并把测试时运行的语句尽量减少,逐渐定位到出错是因为调用了dlist_get_by_index()函数。
# 为了方便说明,后来添加打印出了test_int_dlist()函数的自动变量i、n、data的地址,分别为0x7fff5541ba7c、0x7fff5541ba78、0x7fff5541ba74,以及int、void*在MAC电脑上的长度,分别为4、8。
# 启动gdb调试,既然出错是因为调用了dlist_get_by_index(),便在其调用的前后分别为310、312行设置断点,刚开始是盲目的打印出在311行运行前后各个变量的对比,后面发现n变量似乎有问题,只要运行了311行,便跳出了for循环。如截图所示,在310行断点打印n的值是100,在312行断点打印n的值是0。
# 后来想起《征服C指针》第二章-C是怎么使用内存的—2.5节自动变量(栈)的描述,对应程序的bug,其原因应该是自动变量压栈后,n和data的内存空间靠近,前面打印出来地址空间分别为0x7fff5541ba78、0x7fff5541ba74,从上往下压栈,程序运行先遇到n后遇到data,使得n在下data在上。
# 由于311行对data进行了强制转换,从int类型转成void**类型(指针类型),前面打印出MAC电脑上int类型长度为4,void*类型(指针类型)长度为8,所以data溢出覆盖了n得内存区域。
# 从程序可以看出data初始值为0,这就解释了为什么运行了311行后n的值变成了0并跳出了for循环。
# 后来对n使用了const修饰,程序运行如常。这又非常奇怪了,前面的Bug应该是data溢出对n造成了覆盖重写,而const修饰了n后,这种覆盖重写应该报错才对吧。
# 也许这样的报错只在编译阶段,但运行却正常不报错。
# 总之感觉这个解决方案并不优雅。