禁用 GCC 优化后,不会发生 __kernel_vsyscall() 崩溃
我的应用程序发生了严重的崩溃。 GDB 总是回溯到__kernel_vsyscall()
。调试后,我在源代码中找不到任何可疑的地方。
但在 GCC 编译器中随机禁用一次“-O3”优化标志似乎可以解决该问题。我不确定这是否是崩溃的原因,或者编译器是否在优化过程中做了一些令人讨厌的事情。任何评论或信息都会有帮助。
在下面显示的一些回溯中,在应用程序代码中观察到的唯一错误是从 MsgQ (buffLen) 接收的缓冲区的长度。但源代码确保通过 MsgQ 发送和接收的消息的最大大小为 2048 字节。无法追踪 msgrcv() 调用返回的长度可能被损坏的原因和时间。
崩溃1:
- __kernel_vsyscall()中的0x00110416
- 来自/lib/libc.so.6的send()中的0x00352391
- 来自/lib/libc.so.6的__vsyslog_chk()中的0x0034d31c来自/lib/libc.so.6
- 的syslog()中的0x0034d5b7
- procType1Msg 中的 0x0804f08f(MsgBuff=0xbfc10275)
- procRcvdMsQBuf 中的 0x080498c5(buffLen=134515184,buff='值优化出')
- 主(argc=3,argv=0xbfc10b24)
崩溃 2:
- __ 中的 0x00110416
- 来自 /lib 的 send() 中的 kernel_vsyscall () 0x00352391 /libc.so.6
- 0x0034d31c 在 __vsyslog_chk () 中,来自 /lib/libc.so.6
- 0x0034d5b7 在 syslog () 中,来自 /lib/libc.so.6
- 0x0806234b 在 dumpMsg (buff=0xbfe01832 "U\006\" x,¡ n,#®U\027\bI@\024",len=23)
- procType1Msg 中的 0x0804e539(MsgBuff=0xbfe01815)
- procRcvdMsQBuf 中的 0x0804956d(buffLen=134515040,buff='值优化出来')
- main (argc=3, argv= 0xbfe020c4)
崩溃 3:
- __kernel_vsyscall () 中的 0x00110416
- msgrcv () 中的 0x00353e3f 来自 /lib/libc.so.6
- getMsgQBuffer 中的 0x080639b9(msg_id=196611, pMsg=0xbfa9d360, lMsgType=0, piError否 = 0xbfa9d35c)
- 0x080497dd 在 main (argc=无法访问地址 0x30003 处的内存)
I had a nasty crash occuring in my application. GDB always backtraced it to __kernel_vsyscall()
. I couldn't find anything suspicious in source code after debugging.
But randomly disabling once '-O3' optimisation flag in GCC compiler seemed to resolve the issue. I am not sure if that is the reason of crash or if compiler might have done something nasty during optimisation. Any comment or information will be helpful.
In some backtraces shown below, the only erroneous thing observed in application code is the length of the buffer received from MsgQ (buffLen). But the source code makes sure that maximum size of messages sent and received over MsgQ is 2048 bytes. Couldn't trace why and when the length returned by msgrcv() call could have got corrupted.
CRASH 1:
- 0x00110416 in __kernel_vsyscall ()
- 0x00352391 in send () from /lib/libc.so.6
- 0x0034d31c in __vsyslog_chk () from /lib/libc.so.6
- 0x0034d5b7 in syslog () from /lib/libc.so.6
- 0x0804f08f in procType1Msg(MsgBuff=0xbfc10275)
- 0x080498c5 in procRcvdMsQBuf(buffLen=134515184,buff='value optimized out')
- main (argc=3, argv=0xbfc10b24)
CRASH 2:
- 0x00110416 in __kernel_vsyscall ()
- 0x00352391 in send () from /lib/libc.so.6
- 0x0034d31c in __vsyslog_chk () from /lib/libc.so.6
- 0x0034d5b7 in syslog () from /lib/libc.so.6
- 0x0806234b in dumpMsg (buff=0xbfe01832 "U\006\" x,¨n,#®U\027\bI@\024",len=23)
- 0x0804e539 in procType1Msg(MsgBuff=0xbfe01815)
- 0x0804956d in procRcvdMsQBuf(buffLen=134515040,buff='value optimized out')
- main (argc=3, argv=0xbfe020c4)
CRASH 3:
- 0x00110416 in __kernel_vsyscall ()
- 0x00353e3f in msgrcv () from /lib/libc.so.6
- 0x080639b9 in getMsgQBuffer(msg_id=196611, pMsg=0xbfa9d360, lMsgType=0, piErrorNo=0xbfa9d35c)
- 0x080497dd in main (argc=Cannot access memory at address 0x30003)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我的猜测是您的代码中某处存在内存损坏(可能是缓冲区溢出)。
当您使用 3 级优化进行编译时,编译器输出的代码是这样的:缓冲区溢出会覆盖一些重要的内容(可能会损坏堆栈?),并且编译器在没有优化标志的情况下运行时生成的非优化代码是不同的因此溢出会覆盖其他内容,并且不会导致此特定症状。该错误可能仍然存在,并且可能以其他方式表现出来,甚至根本不表现出来 - 直到您更改了一些不相关的内容,然后它会再次咬您。
__kernel_vsyscall() 只是一个 glibc 函数,每当您执行系统调用时都会在内部调用该函数。那里没有什么重要的事情。
我的建议:在 valgrind 下运行你的程序。它很可能会为您找到内存溢出的情况。
My guess is that you have a memory corruption (probably buffer overflow) somewhere in your code.
When you compile with level 3 optimization the code the compiler outputs is such that the buffer overruns writes over something important (maybe corrupts the stack?) and it so happens that the non optimized code produced by the compiler when running with no optimization flag is different so the overflow runs over something else and does not cause this specific symptom. The bug is probably still there and it may manifest itself in other ways or even not at all - until you change something non related and then it will bite you again.
The __kernel_vsyscall() thing is simply the a glibc function that is called internally whenever you do a syscall. There is nothing significant there.
My recommendation: run your program under valgrind. It will most likely find the memory overrun for you.