2016-11-12 8 views
3

ゴランとプログラミングには初めてです。ゴランセグメンテーションフォールト(コアダンプ)

正規表現に一致するファイルをあるディレクトリから別のディレクトリに移動する小さなプログラムを作成しました。

プログラムは、(最終)のUbuntu 16.04上およびCentOSに6.8上で正常に実行され

特定のCentOSマシン上で(私は1つの正確なバージョンを知らない。私はそれが6である知っているのですか?と

セグメンテーションフォールト(コアダンプ)

は、私の研究は、OSは私がメモリにアクセスすることを許可していないときにこのエラーが発生することを示しています。それは私が得る、)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") 
} 
+0

多少なりとも(類似した場合)(https://github.com/mhausenblas/cinf/issues/1)、それが何であるかを決して理解できませんでした。 1つの仮説は、クロスコンパイルが根本的な原因であったということです(私がMacOSで構築して以来)。 –

+1

オプション-ldflags "-w"を使用してプログラムをコンパイルしてください(たとえば、-ldflags "-w" prog.goをビルドして)gdb(gdb prog)に変換して実行してください(実行してください)。問題が発生した場合は、その時点でバックトレースを表示してください(bt)。 – lofcek

+0

問題のあるマシンにプログラムを構築しましたが、今は動作します。 – user3017869

答えて

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") 
} 

あなたがプログラムに何を入力しているのか分かりませんが、私が見ることのできるものはセグメンテーション違反の原因になります。

関連する問題