Home IT Linux Windows Database Network Programming Server Mobile  
           
  Home \ Programming \ Debugging with GDB tool Go     - Sublime Text 3 shortcuts summary (Linux)

- CentOS 5.5 install ntop (Linux)

- mysqldump implement database logical backup (Database)

- MySQL master-slave delay problem (Database)

- RMAN parameters of ARCHIVELOG DELETION (Database)

- How to use OpenVPN and PrivacyIDEA build two-factor authentication for remote access (Server)

- Ceph distributed storage system is installed on a CentOS 7.1 (Server)

- Elaborate 10-point difference between the new and malloc (Programming)

- Ubuntu install Lighttpd + Mono support .net (Linux)

- Java string equal size comparison (Programming)

- Setting grep Highlight Matches (Linux)

- grep command output highlighted word (Linux)

- Check the Linux server performance with ten or so commands in a minute (Server)

- awk variables (Linux)

- numpy and SciPy installation under Python for scientific computing package (Linux)

- Binary tree traversal: the first sequence in order preorder recursive and non-recursive and traversal sequence (Programming)

- Detailed installation of CentOS 6.x (Linux)

- Shared directory settings between Linux and Linux (Linux)

- Java Learning: elegant string (Programming)

- Linux file permissions to modify the command: chmod (Linux)

 
         
  Debugging with GDB tool Go
     
  Add Date : 2018-11-21      
         
       
         
  Troubleshooting applications is more complex, especially in high concurrency processing Go like this language. It is easier to use print print statements in specific positions to determine the status of the program, but this method is difficult to develop in accordance with the conditions to dynamically respond to your code.

The debugger provides an incredibly powerful troubleshooting mechanism. Add to troubleshoot code can subtly affect how the application runs. The debugger can give you more precise being confused view.

There have been many Go debugger exist, some of which are not very good at the debugger is to inject code at compile time by providing an interactive terminal. gdb debugger allows you to debug precompiled binaries, as long as they have the information connected to debug, modify the source code is not used. This is a very nice feature, so you can take a product from your deployment environment and the flexibility to debug it. You can read more about gdb from Golang official document, then this simple guide will explain the use of gdb debugger to debug applications Go basic usage.

Here gdb will announce some of the latest updates, the most special is to replace the -> operator symbol to access the object properties. Remember that there may be here in gdb and Go releases subtle changes. This guide based on gdb 7.7.1 and go 1.5beta2.

Start gdb debugging

To experiment gdb I use a test program, complete source code can be viewed on gdb_sandbox_on_Github. Let's start with a very simple program started:

package main
 
import (
    "Fmt"
)
 
func main () {
    for i: = 0; i < 5; i ++ {
        fmt.Println ( "looping")
    }
    fmt.Println ( "Done")
}
We can run this code and see its output and we thought the same:

$ Go run main.go
looping
looping
looping
looping
looping
Done
We have to debug the program it. First, go build compiled into a binary file, then use the binary file path as a parameter to run gdb. Depending on your settings, you can also use the source command to get the Go runtime (Go runtime) support. Now that we have the gdb command line, we can set a breakpoint to it before running our binary files.

$ Go build -gcflags "-N -l" -o gdb_sandbox main.go
$ Ls
gdb_sandbox main.go README.md
$ Gdb gdb_sandbox
....
(Gdb) source /usr/local/src/go/src/runtime/runtime-gdb.py
Loading Go Runtime support.
First off, we set a breakpoint in the for loop (b) to view the execution time of each cycle we will have what the status code. We can use a variable print (p) command to check the current content, as well as list (l) and backtrace (bt) command to view the current step around the code. You can use the program runs next (n) to the next step or use the breakpoint (c) execution to the next breakpoint.

(Gdb) b main.go: 9
Breakpoint 1 at 0x400d35: file /home/bfosberry/workspace/gdb_sandbox/main.go, line 9.
(Gdb) run
Starting program: /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/gdb_sandbox Breakpoint 1, main.main () at
/home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:9
9 fmt.Println ( "looping")
(Gdb) l
4 "fmt"
5)
6
7 func main () {
8 for i: = 0; i < 5; i ++ {
9 fmt.Println ( "looping")
10} `
11 fmt.Println ( "Done")
12}
(Gdb) p i
$ A = 0
(Gdb) n
looping
Breakpoint 1, main.main () at
/home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:9
9 fmt.Println ( "looping")
(Gdb) p i
$ 2 = 1
(Gdb) bt
# 0 main.main () at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:9
We can set a breakpoint at line number associated with the file, the line number in the file GOPATH bag or a function. The following is also a valid breakpoint:

(Gdb) b github.com/bfosberry/gdb_sandbox/main.go:9
(Gdb) b 'main.main'
Structs

We can use a little more complicated to code example demonstrates how to debug. We will use the f function generates a simple pair, x and y, when x is equal to y = f (x), otherwise = x.

type pair struct {
    x int
    y int
}
 
func handleNumber (i int) * pair {
    val: = i
    if i% 2 == 0 {
        val = f (i)
    }
    return & pair {
       x: i,
       y: val,
    }
}
 
func f (int x) int {
    return x * x + x
}
You can also change the code in the loop to access these new functions.

    p: = handleNumber (i)
    fmt.Printf ( "% + v \ n", p)
    fmt.Println ( "looping")
Because we need to debug the variable y. We can put a breakpoint where y is set then single step. You can use the info args View function parameters before bt can return to the current traceback.

(Gdb) b 'main.f'
(Gdb) run
Starting program: /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/gdb_sandbox
 
Breakpoint 1, main.f (x = 0, ~ anon1 = 833492132160)
    at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:33
33 return x * x + x
(Gdb) info args
x = 0
(Gdb) continue
Breakpoint 1, main.f (x = 0, ~ anon1 = 833492132160)
    at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:33
33 return x * x + x
(Gdb) info args
x = 2
(Gdb) bt
# 0 main.f (x = 2, ~ anon1 = 1)
    at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:33
# 1 0x0000000000400f0e in main.handleNumber (i = 2, ~ anon1 = 0x1)
    at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:24
# 2 0x0000000000400c47 in main.main ()
    at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:14
Because we are in such a condition in the variable y is a function f is set, we can jump to the context of this function and examine the code heap area. The application is running, we can set a breakpoint on a higher level and check its status.

(Gdb) b main.go: 26
Breakpoint 2 at 0x400f22: file
/home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go, line 26.
(Gdb) continue
Continuing.
Breakpoint 2, main.handleNumber (i = 2, ~ anon1 = 0x1)
    at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:28
28 y: val,
(Gdb) l
23 if i% 2 == 0 {
24 val = f (i)
25}
26 return & pair {
27 x: i,
28 y: val,
29}
30}
31
32 func f (x int) int {
(Gdb) p val
$ 1 = 6
(Gdb) p i
$ 2 = 2
If we continue to stay in this walk we will cross the breakpoint in this function breakpoint 1, and will immediately trigger a breakpoint in HandleNumer function, because the function f is performed only once every variable i. We can temporarily break 2 does not work to prevent this from happening.

(Gdb) disable breakpoint 2
(Gdb) continue
Continuing.
& {X: 2 y: 6}
looping
& {X: 3 y: 3}
looping
[New LWP 15200]
[Switching to LWP 15200]
Breakpoint 1, main.f (x = 4, ~ anon1 = 1)
    at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:33
33 return x * x + x
(Gdb)
We were also able to use clear and delete breakpoint NUMBER to clean and remove breakpoints. Dynamically generated and tied breakpoints, we can effectively move back and forth in the application flow.

Slices and Pointers

The example program too simple, just use the integer and string, so we will write a little bit complicated. First, add a slice (slice types) a pointer to the main function, and save the resulting pair, we will need it later.

    var pairs [] * pair
    for i: = 0; i < 10; i ++ {
        p: = handleNumber (i)
        fmt.Printf ( "% + v \ n", p)
        pairs = append (pairs, p)
        fmt.Println ( "looping")
        }
Now let's check out the slice or generate pairs, we first look into an array of the slice. Because handleNumber returns a * pair type, we need to reference this pointer to access struct (structure) properties.

(Gdb) b main.go: 18
Breakpoint 1 at 0x400e14: file /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go, line 18.
(Gdb) run
Starting program: /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/gdb_sandbox & {x: 0 y: 0}
 
Breakpoint 1, main.main () at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:18
18 fmt.Println ( "looping")
(Gdb) p pairs
$ 1 = [] * main.pair = {0xc82000a3a0}
(Gdb) p pairs [0]
Structure has no component named operator [].
(Gdb) p pairs.array
$ 2 = (struct main.pair **) 0xc820030028
(Gdb) p pairs.array [0]
$ 3 = (struct main.pair *) 0xc82000a3a0
(Gdb) p * pairs.array [0]
$ 4 = {x = 0, y = 0}
(Gdb) p (* pairs.array [0]). X
$ 5 = 0
(Gdb) p (* pairs.array [0]). Y
$ 6 = 0
(Gdb) continue
Continuing.
looping
& {X: 1 y: 1}
 
Breakpoint 1, main.main () at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:18
18 fmt.Println ( "looping")
(Gdb) p (pairs.array [1] [5]). Y
$ 7 = 1
(Gdb) continue
Continuing.
looping
& {X: 2 y: 6}
 
Breakpoint 1, main.main () at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:18
18 fmt.Println ( "looping")
(Gdb) p (pairs.array [2] [6]). Y
$ 8 = 6
(Gdb)
Here you will find gdb not sure pairs is a slice type, we can not directly access its properties, in order to access its members we need to use pairs.array into an array, then we can check slice of length (length) and capacity (capacity):

(Gdb) p $ len (pairs)
$ 12 = 3
(Gdb) p $ cap (pairs)
$ 13 = 4
X and y values then we can make cycle times, and increase the listener through the member of unused slice method, is to be noted that, where the struct attribute can be accessed through a pointer, so p pairs.array [2] .y as possible.

Goroutines

Now that we have access to struct and slice, here come a little more complicated procedures bars. Let's add some goroutines to mian function, parallel processing of each number, the results returned into the channel (chan) in:

    pairs: = [] * pair {}
    pairChan: = make (chan * pair)
    wg: = sync.WaitGroup {}
        for i: = 0; i < 10; i ++ {
          wg.Add (1)
          go func (val int) {
            p: = handleNumber (val)
            fmt.Printf ( "% + v \ n", p)
            pairChan < - p
            wg.Done ()
            } (I)
    }
    go func () {
            for p: = range pairChan {
              pairs = append (pairs, p)
            }
    } ()
    wg.Wait ()
    close (pairChan)
If I wait WaitGroup finished and then check the results of pairs slice, we can expect the content is exactly the same, although it may be some sort of discrepancy. gdb real power comes from it can be checked in goroutines is running:

(Gdb) b main.go: 43
Breakpoint 1 at 0x400f7f: file /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go, line 43.
(Gdb) run
Starting program: /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/gdb_sandbox
 
Breakpoint 1, main.handleNumber (i = 0, ~ r1 = 0x0)
    at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:43
43 y: val,
(Gdb) l
38 if i% 2 == 0 {
39 val = f (i)
40}
41 return & pair {
42 x: i,
43 y: val,
44}
45}
46
47 func f (x int) int {
(Gdb) info args
i = 0
~ R1 = 0x0
(Gdb) p val
$ A = 0
You will find our place in the code segment goroutine to be executed in a breakpoint, from here we can check into local variables, and processes other goroutines:

(Gdb) info goroutines
  1 waiting runtime.gopark
  2 waiting runtime.gopark
  3 waiting runtime.gopark
  4 waiting runtime.gopark
* 5 running main.main.func1
  6 runnable main.main.func1
  7 runnable main.main.func1
  8 runnable main.main.func1
  9 runnable main.main.func1
* 10 running main.main.func1
  11 runnable main.main.func1
  12 runnable main.main.func1
  13 runnable main.main.func1
  14 runnable main.main.func1
  15 waiting runtime.gopark
(Gdb) goroutine 11 bt
# 0 main.main.func1 (val = 6, pairChan = 0xc82001a180, & wg = 0xc82000a3a0)
    at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:19
# 1 0x0000000000454991 in runtime.goexit () at /usr/local/go/src/runtime/asm_amd64.s:1696
# 2 0x0000000000000006 in ?? ()
# 3 0x000000c82001a180 in ?? ()
# 4 0x000000c82000a3a0 in ?? ()
# 5 0x0000000000000000 in ?? ()
(Gdb) goroutine 11 l
48 return x * x + x
49}
(Gdb) goroutine 11 info args
val = 6
pairChan = 0xc82001a180
& Wg = 0xc82000a3a0
(Gdb) goroutine 11 p val
$ 2 = 6
Here we do the first thing is to list all goroutine running, and to determine that one we are dealing with. Then we can see some backtracking, and send any debug commands to goroutine. This backtracking and inventory list and is not accurate, how to get back more accurately, info args goroutine show on our local variables, as well as the main function of the variables available, goroutine outside the function & use the prefix.

in conclusion

When debugging an application, incredibly powerful gdb. But it is still a relatively new thing, not all is perfect place to work. The latest stable version of gdb, go 1.5 beta2, there are many places to have a breakthrough:

Interfaces

According to the article on the blog go, go of interfaces should have been supported, which allows gdb dynamic projection of its base type. This should be considered a breakthrough.

Interface {} type

There is no way for the conversion interface {} its type.

Lists the different points of goroutine

Lists surrounding code in other goroutine will result in a drift of some number of lines, resulting in gdb that the current number of rows exceeds the range of files and throws an error:

(Gdb) info goroutines
  1 waiting runtime.gopark
  2 waiting runtime.gopark
  3 waiting runtime.gopark
  4 waiting runtime.gopark
* 5 running main.main.func1
  6 runnable main.main.func1
  7 runnable main.main.func1
  8 runnable main.main.func1
  9 runnable main.main.func1
* 10 running main.main.func1
  11 runnable main.main.func1
  12 runnable main.main.func1
  13 runnable main.main.func1
  14 runnable main.main.func1
  15 waiting runtime.gopark
(Gdb) goroutine 11 bt
# 0 main.main.func1 (val = 6, pairChan = 0xc82001a180, & wg = 0xc82000a3a0)
    at /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go:19
# 1 0x0000000000454991 in runtime.goexit () at /usr/local/go/src/runtime/asm_amd64.s:1696
# 2 0x0000000000000006 in ?? ()
# 3 0x000000c82001a180 in ?? ()
# 4 0x000000c82000a3a0 in ?? ()
# 5 0x0000000000000000 in ?? ()
(Gdb) goroutine 11 l
48 return x * x + x
49}
(Gdb) goroutine 11 l
Python Exception < class 'gdb.error'> Line number 50 out of range; /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go has 49 lines .:
Error occurred in Python command: Line number 50 out of range; /home/bfosberry/.go/src/github.com/bfosberry/gdb_sandbox/main.go has 49 lines.
Goroutine debugging is not stable

Processing goroutines often unstable; I encountered the implementation of a simple command generates an error. At this stage you should be prepared to deal with similar problems.

gdb support Go configuration is very troublesome

Run gdb debugging support Go configuration is very troublesome for the correct path in conjunction with the build flags, as well as gdb automatically loads can not function like a normal job. First, Go run-time support is generated through an initialization error gdb initialization file to load. This requires manually through a command source to load, debug shell that needs to be initialized as described in the guide inside.

When should I use a debugger?

So under what circumstances the use of gdb more useful? Use print language and debugging code is more targeted approach.

When the time is not appropriate to modify the code.

When debugging a problem, but do not know the source, dynamic breakpoints may be more effective.

When contains many goroutines time, pause and review the state of the program will be better.
     
         
       
         
  More:      
 
- Linux beginners should know 12 commands (Linux)
- Vim Common Command Summary (Linux)
- Install JDK 1.7 + Eclipse in CentOS 6.4 in (Linux)
- Linux vi command list (Linux)
- Zabbix monitoring different versions of RAID installation and monitoring and MySQL master-slave monitor (Server)
- Sublime Text - Opens the current file in a browser (Linux)
- Why JavaScript basic types can invoke methods (Programming)
- How to import JNI resulting .so libraries in Android Studio (Programming)
- Using Python and OpenCV detecting image barcode (Programming)
- Ubuntu deployment Flask + UWSGI + Nginx Comments (Server)
- CentOS 6.x and CentOS7 installation RPMforge (Linux)
- Linux Monitoring Command (Linux)
- Ubuntu Tutorial: E: Failed to get lock / var / lib / apt / lists / lock - open (Linux)
- ActiveMQ5.11.1 and JDK version matching relation (Linux)
- A detailed introduction to the Hadoop ecosystem (Server)
- Linux IPTables anti-DDOS attack Shell Scripting (Linux)
- Programmer editor Vim (Linux)
- Mutt - an email client that sends messages through the terminal (Linux)
- Linux Getting Started tutorial: Experience KVM Virtual Machine chapter (Linux)
- Binder began to talk about inter-process communication mechanism from Android AIDL (Programming)
     
           
     
  CopyRight 2002-2016 newfreesoft.com, All Rights Reserved.