Golang 分段错误(核心已转储)

huangapple go评论81阅读模式
英文:

Golang segmentation fault (core dumped)

问题

我是你的中文翻译助手,以下是你提供的代码的翻译:

package main

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

func main() {

	batch := flag.Int("batch", 0, "要处理的文件数量")
	pattern := flag.String("pattern", "", "要匹配的字符串模式")
	dir := flag.Int("dir", 0, "从字符串模式中获取的键")
	confirm := flag.String("move", "no", "指示程序是否应移动文件的标志")

	flag.Parse()

	d, err := os.Open(".")
	if err != nil {
		log.Fatal("无法打开目录。", err)
	}

	files, err := d.Readdir(*batch)
	if err != nil {
		log.Fatal("无法读取目录。", 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 匹配 %s\n 目录名 = %s\n -----------------------\n", fname, *pattern, dest)

			case "yes":
				// 所有目录都应该是一个数字。
				// 如果目录不匹配正则表达式,则终止执行
				if match, err := regexp.Match("[0-9]", []byte(dest)); match == false {
					log.Fatalf("预期的目录名与准备好的目录不匹配。\n 预期的目录名必须是一个数字(正则表达式[0-9])| 当前目录名为:%s\n", dest)
					if err != nil {
						log.Fatal(err)
					}
				}

				// 检查目录是否存在。如果不存在,则创建它
				if _, err := os.Stat(dest); os.IsNotExist(err) {
					err = os.Mkdir(dest, 0777)
					if err != nil {
						log.Fatal("无法创建目录。", err)
					}
				}
				err = os.Rename(fname, fmt.Sprintf("%s/%s", dest, fname))
				if err != nil {
					log.Fatal("无法移动文件。", err)
				}
				fmt.Printf("将 %s 移动到 %s\n", fname, dest)
			}
		}
	}
	fmt.Println("退出")
}

希望对你有帮助!如果你有任何其他问题,请随时问我。

英文:

I'm new to golang and programming.

I have written a small program that moves files matching a regex from one directory to another.

The program runs successfully on ubuntu 16.04 and on a Centos 6.8 (Final)

On a certain Centos machine (I don't know the exact version of that one. I do know it is 6.? and it is lower than 6.8), I get:

> Segmentation fault (core dumped)

My research shows that this error occurs when the OS does not allow me to access memory.

Can somebody tell me where it goes wrong in my code. Also please point out bad practices if you see any.

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

得分: 2

我的第一个猜测是你超出了's'数组的边界:

dest := s[*dir]

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

package main
import (
"flag"
"fmt"
"log"
"os"
"regexp"
"strings"
)
func main() {
batch := flag.Int("batch", 0, "要处理的文件数量")
pattern := flag.String("pattern", "", "要匹配的字符串模式")
dir := flag.Int("dir", 0, "从strings.Split(pattern, '')中获取的键")
confirm := flag.String("move", "no", "指示程序是否应移动文件的标志")
flag.Parse()
d, err := os.Open(".")
if err != nil {
log.Fatal("无法打开目录。", err)
}
defer d.Close() // [Added] 如果是目录可能不需要,但不会有坏处
files, err := d.Readdir(*batch)
if err != nil {
log.Fatal("无法读取目录。", 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] 在使用之前对*dir索引进行合理性检查
if *dir >= len(s) {
log.Fatalf("dir超出范围:dir=%d len(s)=%d\n", *dir, len(s))
}
dest := s[*dir]
switch *confirm {
case "no":
fmt.Printf(" %s  匹配  %s\n 目录名称 =  %s\n -----------------------\n", fname, *pattern, dest)
case "yes":
// 所有目录都应该是一个数字。
// 如果目录与正则表达式不匹配,则终止执行
if match, err := regexp.Match("[0-9]", []byte(dest)); match == false {
log.Fatalf("预期的目录名称与准备好的目录不匹配。\n 预期的目录名称必须是一个数字(正则表达式[0-9])| 当前目录名称为:%s\n", dest)
if err != nil {
log.Fatal(err)
}
}
// 检查目录是否存在。如果不存在,则创建它
if _, err := os.Stat(dest); os.IsNotExist(err) {
err = os.Mkdir(dest, 0777)
if err != nil {
log.Fatal("无法创建目录。", err)
}
}
err = os.Rename(fname, fmt.Sprintf("%s/%s", dest, fname))
if err != nil {
log.Fatal("无法移动文件。", err)
}
fmt.Printf("将 %s 移动到 %s\n", fname, dest)
// [Added]:确保处理非'yes/no'的答案
default:
log.Fatalf("confirm无效 '%s'\n", *confirm)
}
}
}
fmt.Println("退出")
}

不确定你输入程序的内容,但我没有看到其他可能导致分段错误的原因。

英文:

My first guess would be you are over-running the bounds of the 's' array:

dest := s[*dir]

I added some safety checks (see [Added]):

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

Not sure what you're inputting to the program but nothing else I can see would cause a segmentation fault.

huangapple
  • 本文由 发表于 2016年11月12日 19:47:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/40562539.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定