You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何附加到进程时strace认为某内存未初始化?

关于strace附加进程时recvfrom参数显示异常的分析

嘿,这个问题我之前也碰到过类似的,其实不是你程序的问题,是strace附加到运行中进程时的初始化特性导致的!

先看你给出的关键输出对比,一目了然:

直接启动跟踪的正常输出

# strace -x -s 10 -e trace=recvfrom ./test
recvfrom(3, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"..., 32, 0, {sa_family=AF_INET, sin_port=htons(42134), sin_addr=inet_addr("127.0.0.1")}, [16]) = 32
recvfrom(3, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"..., 32, 0, {sa_family=AF_INET, sin_port=htons(49442), sin_addr=inet_addr("127.0.0.1")}, [16]) = 32

附加到运行中进程的异常输出

# ./test &
# strace -x -s 10 -e trace=recvfrom -p $!
strace: Process 18916 attached
recvfrom(3, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"..., 32, 0, {sa_family=AF_INET, sin_port=htons(50906), sin_addr=inet_addr("127.0.0.1")}, [1999040176->16]) = 32
recvfrom(3, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"..., 32, 0, {sa_family=AF_INET, sin_port=htons(52956), sin_addr=inet_addr("127.0.0.1")}, [16]) = 32

现象背后的原因

你看到的两种情况核心差异在于strace开始跟踪进程的时机:

  • 直接用strace ./test启动程序:strace从进程创建的第一步就全程跟踪,它能在每个recvfrom进入内核前,准确读取到.data段里初始化好的addrlen值(也就是16)。而且因为你用的是AF_INET地址,长度正好是16,内核返回后不会修改这个值,所以每次都显示[16]。
  • 附加到已经在运行的进程:strace是中途插进来的,它需要先暂停进程,然后初始化自身对目标进程内存、寄存器的访问环境。第一次捕获到recvfrom的时候,这个初始化还没完全搞定,导致它在进入内核前读取addrlen时拿到了一段无效的垃圾值(就是你看到的那个大数字)。等内核完成调用返回后,strace的初始化已经完成,就能正常读取到正确的16了,所以后续调用都显示[16]。

为什么第一次读取会出问题?

strace是靠ptrace系统调用接管目标进程的:当你附加到运行中进程时,strace先给进程发信号让它暂停,然后才开始设置自己的跟踪环境(包括建立对目标进程用户空间内存的访问通道)。第一次拦截到系统调用时,这个环境还没完全准备好,所以读出来的是垃圾数据。而之后的调用,环境已经就绪,读取就正常了。

你的MIPS程序完全没问题

看你写的汇编代码,逻辑非常清晰:

.section .text
.global __start
__start:
# socket
li $v0,4183
li $a0,2
li $a1,1
li $a2,0
syscall
sw $v0,sockfd
# bind
li $v0,4169
lw $a0,sockfd
la $a1,sockaddr_b
li $a2,16
syscall
loop:
# recvfrom
li $v0,4176
lw $a0,sockfd
la $a1,buffer
li $a2,32
li $a3,0
la $t0,sockaddr_a
sw $t0,16($sp)
la $t0,addrlen
sw $t0,20($sp)
syscall
j loop
.section .bss
sockaddr_a: .space 16
buffer: .space 32
sockfd: .space 4
.section .data
addrlen: .int 16
.section .rodata
sockaddr_b: .hword 2,1234,0,0

你每次循环都会把.data段中静态初始化的addrlen变量地址传到栈上作为recvfrom的参数,这个变量的值从始至终都是16(因为AF_INET地址长度匹配,内核不会修改它),程序本身没有任何内存未初始化的问题。

哪怕你反复分离再附加,每次第一次的recvfrom都会出现这个现象——这纯粹是strace的初始化小特性,不是程序bug。


内容的提问来源于stack exchange,提问作者forest

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:36:02