关于GCC的奇怪问题,高手进。

sherlock_lai 2009-10-14 05:17:11
现在遇到的问题是,同样的程序,里面两个.o文件链接顺序不一样,会对程序的结果造成影响,这是什么原理?

manager说是GCC链接时候发生异常,把某个变量或形参覆盖了?

大家有没有遇到过这种问题? 要怎么解决?
...全文
118 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
sherlock_lai 2009-10-15
  • 打赏
  • 举报
回复
帖子+到100分,结贴给分了!
sherlock_lai 2009-10-15
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 elfirex 的回复:]
不好意思,理解错了,贴一下你程序中write的顺序吧,不是很明确你怎么做的。
[/Quote]
。。。。我在write的最开头加了barrier();竟然好了,谢谢了!兄弟 谢谢! 代码如下


static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
loff_t *offset)
{
int ret;
char *tmp;
struct i2c_client *client = (struct i2c_client *)file->private_data;

#ifdef DEBUG
struct inode *inode = file->f_dentry->d_inode;
#endif /* DEBUG */

barrier();
if (count > 8192)
count = 8192;
/* copy user space data to kernel space. */
tmp = kmalloc(count,GFP_KERNEL);
if (tmp==NULL)
return -ENOMEM;
if (copy_from_user(tmp,buf,count)) {
kfree(tmp);
return -EFAULT;
}

#ifdef DEBUG
printk(KERN_DEBUG "i2c-dev.o: i2c-%d writing %d bytes.\n",MINOR(inode->i_rdev),
count);
#endif
ret = i2c_master_send(client,tmp,count);
kfree(tmp);
return ret;
}
zkuang82 2009-10-15
  • 打赏
  • 举报
回复
不好意思,理解错了,贴一下你程序中write的顺序吧,不是很明确你怎么做的。
sherlock_lai 2009-10-15
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 elfirex 的回复:]
你的驱动写在用户空间吗?用户空间似乎没有这样的东西吧。你试试直接用内核的头文件,我没试过在用户空间干这种事情^_^。
[/Quote]
哦,我驱动是在内核空间的,那再驱动的write里加这个函数吗? 还是要在init或open的时候加?
zkuang82 2009-10-15
  • 打赏
  • 举报
回复
你的驱动写在用户空间吗?用户空间似乎没有这样的东西吧。你试试直接用内核的头文件,我没试过在用户空间干这种事情^_^。
sherlock_lai 2009-10-15
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 elfirex 的回复:]
在各个write之间加上memory barrier吧,保证你的程序按顺序执行。
[/Quote]
楼上的,用户空间这个函数杂用? 头文件是哪个? 谢谢了!试试!
zkuang82 2009-10-15
  • 打赏
  • 举报
回复
在各个write之间加上memory barrier吧,保证你的程序按顺序执行。
sherlock_lai 2009-10-15
  • 打赏
  • 举报
回复
但是错误为什么只会出现一次? 如果第一次分成了2次write,但是第二次我再去执行这个程序,结果必然正确!
考。。。这个问题太奇怪了,如果有几率的话,我再一次执行,应该也会出现分成2次write的情况啊!!!

sherlock_lai 2009-10-15
  • 打赏
  • 举报
回复
通过示波器抓波形,搞了半天,终于找到原因,是write函数的问题,我写一个字节都是通过write(fd,buf,2)这样的函数,buf[0]=寄存器地址,buf[1]=数据。照理说,按这个函数,I2C一次写寄存器的时序应该是下面第一种情形:

第一种:先写器件地址,然后寄存器地址,然后再写数据。 这样就能正确写入数据,读出也正确。

如果我换成2次wirte(fd,&buf[0],1); write(fd,&buf[1],1);,则会出现第二种时序:

第二种:写器件地址,写寄存器地址,写器件地址,写数据。 这种时序是无论如何都不会有正确结果的。

而我将这个写的子函数放在A文件里,他总是出现第一种时序,而我放到B文件里,他有几率出现第二种时序!!这难道是内核IIC write驱动的问题?? 我程序没变,还是write(fd,buf,2),但是驱动为什么有几率会处理成2次write???还需要再查!
zkuang82 2009-10-15
  • 打赏
  • 举报
回复
看来不像是GCC的问题。
问题在于你有没有用memory barrier。读到上次的值,似乎是因为这个值在cache中。
你试试在你对硬件地址进行操作前后加上memory barrier,然后把那些硬件地址声明为volatile。
renjianxin520 2009-10-15
  • 打赏
  • 举报
回复
少有的问题?等待正解
sherlock_lai 2009-10-15
  • 打赏
  • 举报
回复
我在子函数里随便加个printf。。。结果程序都正确了,把printf注释掉,又不行了。
sherlock_lai 2009-10-15
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 elfirex 的回复:]
除非是GCC的bug,一般不会发生这种问题。
形参怎么会被覆盖?我的理解是形参信息估计用来告诉在stack frame中预留多少位置的吧?或者是确定需要怎样的寄存器来进行参数传递。
变量有可能被覆盖,但应该只限于一些静态数据或者是全局数据吧?如果你的ld脚本做了些特殊处理,链接时的确有可能覆盖相关位置的信息,但应该会有警告或者错误吧?

能不能说明下你程序是怎么被影响的?
[/Quote]
我的程序总共几十个文件,但是我在main里把其他全注释了,只剩调用一个子函数。

子函数的功能就是往IIC器件某地址写一个值,然后读出来,再print,然后exit(0)。
如果把这个函数放在文件A里编译,读出的值正确,如果放在文件B里编译,则有几率读出上一次的值,也就是说有时候是读出刚写入的值,是对的。
steptodream 2009-10-15
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 delphiwcdj 的回复:]
还没见过 up
[/Quote]
xhd3767 2009-10-14
  • 打赏
  • 举报
回复
加上这样的参数
-Wl,--start-group (lib) -Wl,--end-group
delphiwcdj 2009-10-14
  • 打赏
  • 举报
回复
还没见过 up
zkuang82 2009-10-14
  • 打赏
  • 举报
回复
除非是GCC的bug,一般不会发生这种问题。
形参怎么会被覆盖?我的理解是形参信息估计用来告诉在stack frame中预留多少位置的吧?或者是确定需要怎样的寄存器来进行参数传递。
变量有可能被覆盖,但应该只限于一些静态数据或者是全局数据吧?如果你的ld脚本做了些特殊处理,链接时的确有可能覆盖相关位置的信息,但应该会有警告或者错误吧?

能不能说明下你程序是怎么被影响的?
sherlock_lai 2009-10-14
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 wxdcxp 的回复:]
你可以用一个文件声明,在另一个文件定义
测试下

[/Quote]
和声明定义没有关系,我的函数直接定义的,没有声明
sherlock_lai 2009-10-14
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 nevil 的回复:]
GCC链接时会对链接文件的顺序有一定的要求,也许这样造成你了的结果不同。

The linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file ‘foo.o’ but before‘bar.o’. If ‘bar.o’ refers to functions in ‘z’, those functions may not be loaded.
[/Quote]
如果not be loaded,应该在编译的时候就报错了吧?
wxdcxp 2009-10-14
  • 打赏
  • 举报
回复
你可以用一个文件声明,在另一个文件定义
测试下
加载更多回复(1)

23,116

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧