Golang分段错误(核心转储)

时间:2016-11-12 11:47:38

标签: go

我是golang和编程新手。

我编写了一个小程序,将匹配正则表达式的文件从一个目录移动到另一个目录。

该程序在ubuntu 16.04和Centos 6.8(最终版)上成功运行

在某台Centos机器上(我不知道那台机器的确切版本。我知道它是6.?它低于6.8),我得到:

  

分段错误(核心转储)

我的研究表明,当操作系统不允许我访问内存时会发生此错误。

有人可以告诉我代码中哪里出错了。如果你看到任何不良行为,也请指出。

package main

import (
    "flag"
    "fmt"
    "log"
    "os"
    "regexp"
    "strings"
)

func main() {

    batch := flag.Int("batch", 0, "the amount of files to be processed")
    pattern := flag.String("pattern", "", "string pattern to be matched")
    dir := flag.Int("dir", 0, "key from strings.Split(pattern, '')")
    confirm := flag.String("move", "no", "flags if program should move files")

    flag.Parse()

    d, err := os.Open(".")
    if err != nil {
        log.Fatal("Could not open directory. ", err)
    }

    files, err := d.Readdir(*batch)
    if err != nil {
        log.Fatal("Could not read directory. ", err)
    }

    for _, file := range files {
        fname := file.Name()
        match, err := regexp.Match(*pattern, []byte(fname))
        if err != nil {
            log.Fatal(err)
        }
        if match == true {

            s := strings.Split(fname, "_")
            dest := s[*dir]

            switch *confirm {
            case "no":
                fmt.Printf(" %s  matches  %s\n Dir name =  %s\n -----------------------\n", fname, *pattern, dest)

            case "yes":
                //all directories are expected to be a number.
                //terminate execution if directory doesn't match regex
                if match, err := regexp.Match("[0-9]", []byte(dest)); match == false {
                    log.Fatalf("Expected directory name does not match prepared directory.\n Expected dir name must be a number (regex [0-9]) | Current dir name is: %s\n", dest)
                    if err != nil {
                        log.Fatal(err)
                    }
                }

                //check if direcotry exists. create it if it doesn't
                if _, err := os.Stat(dest); os.IsNotExist(err) {
                    err = os.Mkdir(dest, 0777)
                    if err != nil {
                        log.Fatal("Could not create directory. ", err)
                    }
                }
                err = os.Rename(fname, fmt.Sprintf("%s/%s", dest, fname))
                if err != nil {
                    log.Fatal("Could not move file. ", err)
                }
                fmt.Printf("Moved %s to %s\n", fname, dest)
            }
        }
    }
    fmt.Println("Exit")
}

1 个答案:

答案 0 :(得分:0)

我的第一个猜测是你过度运行's'数组的界限:

dest := s[*dir]

我添加了一些安全检查(参见[已添加]):

package main

import (
    "flag"
    "fmt"
    "log"
    "os"
    "regexp"
    "strings"
)

func main() {
    batch := flag.Int("batch", 0, "the amount of files to be processed")
    pattern := flag.String("pattern", "", "string pattern to be matched")
    dir := flag.Int("dir", 0, "key from strings.Split(pattern, '')")
    confirm := flag.String("move", "no", "flags if program should move files")

    flag.Parse()

    d, err := os.Open(".")
    if err != nil {
        log.Fatal("Could not open directory. ", err)
    }
    defer d.Close() // [Added] probably not needed if a directory but doesn't hurt

    files, err := d.Readdir(*batch)
    if err != nil {
        log.Fatal("Could not read directory. ", err)
    }

    for _, file := range files {
        fname := file.Name()
        match, err := regexp.Match(*pattern, []byte(fname))
        if err != nil {
            log.Fatal(err)
        }
        if match == true {
            s := strings.Split(fname, "_")

            // [Added] Sanity check *dir index before using
            if *dir >= len(s) {
                log.Fatalf("dir is out of range: dir=%d len(s)=%d\n", *dir, len(s))
            }

            dest := s[*dir]

            switch *confirm {
            case "no":
                fmt.Printf(" %s  matches  %s\n Dir name =  %s\n -----------------------\n", fname, *pattern, dest)

            case "yes":
                //all directories are expected to be a number.
                //terminate execution if directory doesn't match regex
                if match, err := regexp.Match("[0-9]", []byte(dest)); match == false {
                    log.Fatalf("Expected directory name does not match prepared directory.\n Expected dir name must be a number (regex [0-9]) | Current dir name is: %s\n", dest)
                    if err != nil {
                        log.Fatal(err)
                    }
                }

                //check if direcotry exists. create it if it doesn't
                if _, err := os.Stat(dest); os.IsNotExist(err) {
                    err = os.Mkdir(dest, 0777)
                    if err != nil {
                        log.Fatal("Could not create directory. ", err)
                    }
                }
                err = os.Rename(fname, fmt.Sprintf("%s/%s", dest, fname))
                if err != nil {
                    log.Fatal("Could not move file. ", err)
                }
                fmt.Printf("Moved %s to %s\n", fname, dest)

                // [Added]: Make sure to handle non 'yes/no' answers
            default:
                log.Fatalf("confirm is invalid '%s'\n", *confirm)
            }
        }
    }
    fmt.Println("Exit")
}

不确定您输入的程序是什么,但我看不到任何其他内容会导致分段错误。