I used strings.Replace in my application to replace prefix '/cloud/app' with '/cloud/data', and got wrong result sometime.
Debuged 'strings.Replace' with gdb i found strings.indexShortStr return bad result, which is written with assembly language and i am not able to debug it.
strings.Replace (stirngs.go: 696) if m := Count(s, old); m == 0 {
stirngs.Count (strings.go: 85) i := Index(s[offset:], sep)
strings.Index (strings_amd64.go:42) return indexShortStr(s, sep)
strings.indexShortStr () at /home/admin/work/tj16/go/go/src/runtime/asm_amd64.s:1743
strings.Index("/cloud/app/abc/abc/abc", "/cloud/app") return an unexpected -1
cause strings.go:87 return
Thread 1 hit Breakpoint 1, main.main () at /home/admin/work/tj16/go/src/my_application/main/test.go:22 warning: Source file is more recent than executable.
22 fmt.Printf("replace: %s\n", strings.Replace(dir, "/cloud/app", "/cloud/data", 1))
(gdb) s
strings.Replace (s="/cloud/app/abc/abc#/abc", old="/cloud/app", new="/cloud/data", n=1, ~r4="") at /home/admin/work/tj16/go/go/src/strings/strings.go:690
warning: Source file is more recent than executable.
690 func Replace(s, old, new1 string, n int) string {
(gdb) n
691 if old == new1 || n == 0 {
(gdb) n
696 if m := Count(s, old); m == 0 {
(gdb) s
strings.Count (s="/cloud/app/abc/abc#/abc", sep="/cloud/app", ~r2=842350510104)
at /home/admin/work/tj16/go/go/src/strings/strings.go:77
77 func Count(s, sep string) int {
(gdb) n
80 if len(sep) == 0 {
(gdb) n
77 func Count(s, sep string) int {
(gdb) n
85 i := Index(s[offset:], sep)
(gdb) p s
$1 = "/cloud/app/abc/abc#/abc"
(gdb) p sep
$2 = "/cloud/app"
(gdb) s
89 n++
(gdb) n
85 i := Index(s[offset:], sep)
(gdb) s
strings.Index (s="/cloud/app/abc/abc#/abc", sep="/cloud/app", ~r2=0)
at /home/admin/work/tj16/go/go/src/strings/strings_amd64.go:25
25 func Index(s, sep string) int {
(gdb) n
28 case n == 0:
(gdb) n
30 case n == 1:
(gdb) n
32 case n == len(s):
(gdb) n
37 case n > len(s):
(gdb) n
39 case n <= shortStringLen:
(gdb) n
41 if len(s) <= 64 {
(gdb) n
42 return indexShortStr(s, sep)
(gdb) s
strings.indexShortStr () at /home/admin/work/tj16/go/go/src/runtime/asm_amd64.s:1743
1743 MOVQ s+0(FP), DI
(gdb) p s
No symbol "s" in current context.
(gdb) n
1745 MOVQ s_len+8(FP), DX
(gdb) n
1746 MOVQ c+16(FP), BP
(gdb) n
1747 MOVQ c_len+24(FP), AX
(gdb) n
1748 MOVQ DI, R10
(gdb) n
1749 LEAQ ret+32(FP), R11
(gdb) n
1750 JMP runtime·indexShortStr(SB)
(gdb) n
runtime.indexShortStr () at /home/admin/work/tj16/go/go/src/runtime/asm_amd64.s:1767
1767 CMPQ AX, DX
(gdb) n
1768 JA fail
(gdb) n
1769 CMPQ DX, $16
(gdb) n
1770 JAE sse42
(gdb) n
1970 MOVL runtime·cpuid_ecx(SB), CX
(gdb) n
1971 ANDL $0x100000, CX
(gdb) n
1972 JZ no_sse42
(gdb) n
1973 CMPQ AX, $12
(gdb) n
1978 JAE _9_or_more
(gdb) n
1979 LEAQ 16(BP), SI
(gdb) n
1980 TESTW $0xff0, SI
(gdb) n
1981 JEQ no_sse42
(gdb) n
1982 MOVOU (BP), X1
(gdb) n
1983 LEAQ -15(DI)(DX*1), SI
(gdb) n
1984 MOVQ $16, R9
(gdb) n
1985 SUBQ AX, R9 // We advance by 16-len(sep) each iteration, so precalculate it into R9
(gdb) n
1991 PCMPESTRI $0x0c, (DI), X1
(gdb) n
1995 CMPQ CX, R9
(gdb) n
1996 JBE sse42_success
(gdb) n
1997 ADDQ R9, DI
(gdb) n
1998 CMPQ DI, SI
(gdb) n
1999 JB loop_sse42
(gdb) n
1991 PCMPESTRI $0x0c, (DI), X1
(gdb) n
1995 CMPQ CX, R9
(gdb) n
1996 JBE sse42_success
(gdb) n
1997 ADDQ R9, DI
(gdb) n
1998 CMPQ DI, SI
(gdb) n
1999 JB loop_sse42
(gdb) n
1991 PCMPESTRI $0x0c, (DI), X1
(gdb) n
1995 CMPQ CX, R9
(gdb) n
1996 JBE sse42_success
(gdb) n
1997 ADDQ R9, DI
(gdb) n
1998 CMPQ DI, SI
(gdb) n
1999 JB loop_sse42
(gdb) n
1991 PCMPESTRI $0x0c, (DI), X1
(gdb) n
1995 CMPQ CX, R9
(gdb) n
1996 JBE sse42_success
(gdb) n
1997 ADDQ R9, DI
(gdb) n
1998 CMPQ DI, SI
(gdb) n
1999 JB loop_sse42
(gdb) n
1991 PCMPESTRI $0x0c, (DI), X1
(gdb) n
1995 CMPQ CX, R9
(gdb) n
1996 JBE sse42_success
(gdb) n
1997 ADDQ R9, DI
(gdb) n
1998 CMPQ DI, SI
(gdb) n
1999 JB loop_sse42
(gdb) n
2000 PCMPESTRI $0x0c, -1(SI), X1
(gdb) n
2001 CMPQ CX, R9
(gdb) n
2002 JA fail
(gdb) n
1964 MOVQ $-1, (R11)
(gdb) n
runtime.indexShortStr () at /home/admin/work/tj16/go/go/src/runtime/asm_amd64.s:1965
1965 RET
(gdb) n
strings.Count (s="/cloud/app/abc/abc#/abc", sep="/cloud/app", ~r2=842350510104)
at /home/admin/work/tj16/go/go/src/strings/strings.go:86
86 if i == -1 {
(gdb) n
87 return n
(gdb) p s
$3 = "/cloud/app/abc/abc#/abc"
(gdb) p sep
$4 = "/cloud/app"
(gdb) l
82 }
83 offset := 0
84 for {
85 i := Index(s[offset:], sep)
86 if i == -1 {
87 return n
88 }
89 n++
90 offset += i + len(sep)
91 }
call: strings.Replace("/cloud/app/abc/abc/abc/123", "/cloud/app", "/cloud/data", 1)
some times "/cloud/app/abc/abc/abc/123" , some times "/cloud/data/abc/abc/abc/123"
I used strings.Replace in my application to replace prefix '/cloud/app' with '/cloud/data', and got wrong result sometime.
expect: "/cloud/data/abc/abc/abc/123"
actual: some times "/cloud/app/abc/abc/abc/123" , some times "/cloud/data/abc/abc/abc/123"
Debuged 'strings.Replace' with gdb i found strings.indexShortStr return bad result, which is written with assembly language and i am not able to debug it.
summary of gdb message
full gdb message
What version of Go are you using (
go version)?go1.8
Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (
go env)?gcc version 4.1.2 20080704 (Red Hat 4.1.2-50)
cpu
model name : Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz
address sizes : 46 bits physical, 48 bits virtual
What did you do?
call: strings.Replace("/cloud/app/abc/abc/abc/123", "/cloud/app", "/cloud/data", 1)
What did you expect to see?
"/cloud/data/abc/abc/abc/123"
What did you see instead?
some times "/cloud/app/abc/abc/abc/123" , some times "/cloud/data/abc/abc/abc/123"