我有一个非常简单的程序,只能在循环中调用recvfrom()
。根据它的manpage,其中一个参数是指向地址长度的指针。此地址在.data
部分初始化为整数值16
。当我附加到已经运行的进程来跟踪它时,我注意到一些奇怪的行为,当我直接跟踪进程时(当我开始跟踪时),这种行为不存在。滚动到行尾:
# 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
recvfrom(3, ^Cstrace: Process 18909 detached
<detached ...>
# ./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
recvfrom(3, ^Cstrace: Process 18916 detached
<detached ...>
当我直接跟踪它时,地址长度参数显示为[16]
,这是有道理的。毕竟,地址是指向值int
的{{1}}的指针。但是,当我附加到进程并跟踪它时,第一个调用显示它未初始化,例如16
。每次我附加时,第一次系统调用都会发生这种情况,但所有后续调用都会将其正确显示为[1999040176->16]
。如果我从进程中分离并重新连接,第一个调用将显示为具有未初始化的内存。
简短说明:
当我在[16]
下运行时,最后一个参数会显示strace
的每个[16]
。
当我在运行时附加到它时,最后一个参数会在第一次调用recvfrom()
时显示[1999040176->16]
之类的内容,并在后续所有调用中显示recvfrom()
。
如果我从中分离并再次附加,则第一次调用[16]
会再次显示此奇怪行为,所有后续调用都会显示预期的recvfrom()
。
这不是编程问题,因为我知道程序本身是正确的。如果重要的是,这是程序(用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