本篇着重讨论一下指针同名问题
问题的产生应该是因为在不同的命名空间有不同的生存期
所以在判断malloc的时候记录下当前命名空间是比较好的,到时候搜查对象访问的时候就在此命名空间找
不过也还有一些情况可能会导致指向同一块内存的对象跨越命名空间1.一个是F1调用F2,F2 return 对象
F2{
dictionary_t* dict = calloc(sizeof(dictionary_t), 1);
return dict;
}
F1{
dictionary_t* dict = F2();
}
那么这个dict即是子函数里calloc的对象
这种还是同名情况 要是上层取别的名字
若dictionary_t* d = F2(); //这个d还是对分配的那一块内存的访问
解决办法:将命名空间从F2变为F1
当F1里赋值语句左边名字不一样时 ,新添一个对象,编号还是F2里对象对应编号,对象的名字把F2等号左边的提取粗来即可
( 设置对象编号是唯一的, malloc一个加一个)
这里遇到的问题:
因为需要提前把等号左边的提取出来,存为othername,当distract为true的时候再进行更改操作
但是当出现函数几层调用并且都返回对象时,比如:
F1{
a = F2();
}
F2{
b=F3( );
return c;
}
F3{
return c;
}
首先从F1执行a = F2(); 将a赋值为othername
进入F2,执行到b=F3( ); 将b赋值为othername,b将之前的a覆盖掉了
检测到F3返回对象时,可新添一个对象并给名字赋值
但是紧接着监测到F2返回对象时,等号左边的a已经被覆盖掉了,取不出来,所以只设置一个othername变量是不能实现的
相当于这种多级调用应该是先进后出的
但是如果是在一个函数中多次调用下层函数,比如:
F1{
a = F2();
b = F3();
}
这种情况还是先进先出的
目前想到的解决方法是:建立一个存放othername类的列表,每个类里面有存放名字和存放命名空间的属性
当要用到othername时,寻找列表中与当前命名空间相同的取出来。
且取出来之后,要将它移除列表(这是因为在一个函数中多次调用下层函数存的几个类命名空间一样)
当return的不是对象时也要赶紧移除,以免干扰后面的
2.对象作为实参传入进去
F1{
int *p,a,b;
p = malloc(...)
F2(p,a,b);
}
F2(int *pp ,int a, int b){
*pp = *pp +1;
}
此处对形参*pp的访问即为F1中对*p的访问。
解决方法:将命名空间F1变为F2
当形参与实参名字不一样时 更改实参对应的编号的对象的名字为形参名字
这里的难点就在于,不知道对象在参数列表里是第几个,要对应的找到形参列表里的名字
简单的来说 要是对对象名左边是括号 那一定第一个;前面n个逗号,就是第n+1个
实现起来的话,可以先取左括号到objectname前一个字符的子字符串,再看这个子字符串里包含几个逗号
再从函数定义的一行找到第n个逗号(左括号)后和第n+1个括号(右括号)前的一段子字符串
当然这个子字符串肯定是 类型 名字 取一个人空格后的字符串即为新名字。
3.让另一个指针指向对象
s = (unsigned short *)src;
也跟上面一样 更改src对应的编号的对象的名字为s
在网上看了一点帖子,有人说不要将两个指针变量指向同一块动态内存,容易引起很严重的问题。
如果将两个指针变量指向同一块动态内存,而其中一个生命期结束释放了该动态内存,这个时候就会出现问题,另一个指针所指向的地址虽然被释放了但该指针并不等于NULL,这就是所谓的悬垂指针错误,这种错误很难被察觉,而且非常严重,因为这时该指针的值是随机的,可能指向一个系统内存而导致程序崩溃。
可怕,benchmark里就有这种情况,你不能保证别人写的代码一定是注意到了这种情形的。
比如这种情况, hash_entry_t* header = h->array[idx]; 更要考虑。
第三种先搁置吧,看到时候是修改下源代码忽略这种情况还是考虑进来。