gcc O2选项造成的错误

ivanwang 2011-02-23 07:11:56
装apache结果出错,invalid argument
debug了一下apache的代码,发现GCC编译时带上了O2的选项,造成了函数调用fstat()出错。
于是我试着自己写了一段测试代码,分别用默认不带优化和带O2优化两种编译,结果果然不带编译的没问题,带了O2选项的返回一个errno为22的“invalid argument”.
测试环境为:
ivan@Redhat101:/localhome/ivan> uname -a
Linux Redhat101 2.6.18-194.el5 #1 SMP Tue Mar 16 21:52:39 EDT 2010 x86_64 x86_64 x86_64 GNU/Linux

ivan@Redhat101:/localhome/ivan> gcc --version
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-48)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

测试代码为:
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
int main ( int argc, char *argv[] )
{
int fd1=-1;
struct stat info1;
fd1=open("/localhome/kana/lingc.txt", O_RDWR);
printf("fd1=%d",fd1);
if(fd1 > 0)
{
if(fstat(fd1,&info1)!=0)
printf("failed to open fd1:%d;errorno:%d\n",fd1,errno);
else printf("sucess");
close(fd1);
}

return 0;
}

请各位指教一下。
或者手头刚好有32位的机器也帮忙验证下,是不是32位就没有这个问题。
...全文
575 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
sherwoodwang 2011-02-28
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 gaosifuti 的回复:]

这个有意思,呵呵,上网查了一下,
extern __inline__ int fstat (int __fd, struct stat *__statbuf) __THROW
{
return __fxstat (_STAT_VER, __fd, __statbuf);
}
// _STAT_VER这个宏是3,和“movl $3, %edi”这一句可以印证,

int __f……
[/Quote]

很有可能。
gaosifuti 2011-02-25
  • 打赏
  • 举报
回复
这个有意思,呵呵,上网查了一下,
extern __inline__ int fstat (int __fd, struct stat *__statbuf) __THROW
{
return __fxstat (_STAT_VER, __fd, __statbuf);
}
// _STAT_VER这个宏是3,和“movl $3, %edi”这一句可以印证,

int __fxstat (int vers, int fd, struct stat *buf)
{
if (vers != _STAT_VER)
{
__set_errno (EINVAL); // 这就是“Invalid argument”
return -1;
}
是不是C库和头文件的版本不一致?
ivanwang 2011-02-25
  • 打赏
  • 举报
回复
0级优化(O0参数)的汇编代码
.file "t.c"
.section .rodata
.LC0:
.string "/localhome/kana/lingc.txt"
.LC1:
.string "fd1=%d"
.align 8
.LC2:
.string "failed to open fd1:%d;errorno:%d\n"
.LC3:
.string "sucess"
.text
.globl main
.type main, @function
main:
.LFB9:
pushq %rbp
.LCFI0:
movq %rsp, %rbp
.LCFI1:
subq $176, %rsp
.LCFI2:
movl %edi, -164(%rbp)
movq %rsi, -176(%rbp)
movl $-1, -4(%rbp)
movl $2, %esi
movl $.LC0, %edi
movl $0, %eax
call open
movl %eax, -4(%rbp)
movl -4(%rbp), %esi
movl $.LC1, %edi
movl $0, %eax
call printf
cmpl $0, -4(%rbp)
jle .L2
leaq -160(%rbp), %rsi
movl -4(%rbp), %edi
call fstat
testl %eax, %eax
je .L4
call __errno_location
movl (%rax), %edx
movl -4(%rbp), %esi
movl $.LC2, %edi
movl $0, %eax
call printf
jmp .L6
.L4:
movl $.LC3, %edi
movl $0, %eax



2级优化(O2选项)的汇编代码:
.file "t.c"
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "/localhome/kana/lingc.txt"
.LC1:
.string "fd1=%d"
.section .rodata.str1.8,"aMS",@progbits,1
.align 8
.LC2:
.string "failed to open fd1:%d;errorno:%d\n"
.section .rodata.str1.1
.LC3:
.string "sucess"
.text
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB20:
pushq %rbx
.LCFI0:
movl $2, %esi
movl $.LC0, %edi
xorl %eax, %eax
subq $144, %rsp
.LCFI1:
call open
movl $.LC1, %edi
movl %eax, %ebx
movl %eax, %esi
xorl %eax, %eax
call printf
testl %ebx, %ebx
jle .L2
movq %rsp, %rdx
movl %ebx, %esi
movl $3, %edi
call __fxstat
testl %eax, %eax
je .L4
call __errno_location
movl (%rax), %edx
movl %ebx, %esi
movl $.LC2, %edi
xorl %eax, %eax
call printf
.L6:
movl %ebx, %edi
call close
.L2:
addq $144, %rsp
ivanwang 2011-02-24
  • 打赏
  • 举报
回复
Hi, 多谢大家。
我修改了下我之前的测试代码,将fstat()调用改为fstat64(),测试代码顺利通过,无论加不加O2的优化选项。
于是去修改了apache的APR代码,加了一个条件判断是否64位,如果是则调用fstat64(),结果apache仍旧是原先的错误,invalid argument()。
纠结死了。
汇编代码还在办公室机器上,回头来帖。
yong_f 2011-02-24
  • 打赏
  • 举报
回复
有可能这个版本的GCC或libc库不支持o2的优化选项。你可以用O3可O4试试
xiaocai0001 2011-02-23
  • 打赏
  • 举报
回复
应该跟GCC的版本有关, 可能是GCC本身的BUG

我就遇到过GCC-4.1.2的BUG, 对于pch文件的支持有BUG (详见http://gcc.gnu.org/bugzilla/show_bug.cgi?id=10591), 换个GCC版本就好了.

我试了一下你的代码, 加-O2, 和不加都一样的结果

gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-27)
sherwoodwang 2011-02-23
  • 打赏
  • 举报
回复
虽然没法再现问题,但是我看看觉得应该是编译器错误,这问题很有趣,因为根据man page,fstat没道理给出invalid argument。把gcc -S和gcc -O2 -S产生的汇编文件发出来看看。
sherwoodwang 2011-02-23
  • 打赏
  • 举报
回复
32位
i486-linux-gnu
gcc version 4.4.5

没有问题,加不加O2都正确执行。

23,114

社区成员

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

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