FilesSearcher 程序 - 程序接收到信号 SIGSEGV,分段错误
FilesSearcher Program - Program received signal SIGSEGV, Segmentation fault
我写了一个简单的程序,可以在文件中搜索特定的文本,但是我得到了这个错误:
Program received signal SIGSEGV, Segmentation fault
.
你能告诉我我错在哪里吗?你能告诉我如何使用 GDB 调试器来获取有关我遇到的错误的信息吗?
(使用 GDB 我得到这个错误:
Program received signal SIGSEGV, Segmentation fault.
0x0000555555557612 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::size() const ()
但我不知道如何获得有关该错误的更多信息,您能解释一下吗?
代码测试程序:
/**
COMPILATION:
g++ test_files_searcher.cpp -o files_searcher.out FilesSearcher_Linux/FilesSearcher.cpp FilesSearcher_Linux/FileContent.cpp
**/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pwd.h>
#include <iostream>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fstream>
#include <vector>
#include "FilesSearcher_Linux/FilesSearcher.h"
#define SIZE_SEARCH_MATRIX 0x6
#define SIZE_EXTS_ARRAY 0x1
int main(){
using namespace std;
std::vector<std::string> matrix = {"test[=11=]", "lol[=11=]", "asd[=11=]", "lmao[=11=]", "rotfl[=11=]"};
std::vector<std::string> exts = {"txt[=11=]"};
FilesSearcher fs = FilesSearcher(matrix, exts);
const char *home_path = fs.get_home_path();
cout << "[+] Home Path: " << home_path << endl;
fs.parse_files(home_path);
if(fs.get_found_files().size() > 0x0){
for(FileContent *fc : fs.get_found_files()){
std::cout << "file path == " << fc->get_path() << " file content == " << fc->get_content() << std::endl;
delete fc;
}
}
}
FilesSearcher.cpp:
#include "FilesSearcher.h"
FilesSearcher::FilesSearcher(std::vector<std::string> keywords, std::vector<std::string> extensions){
mKeywords = keywords;
mExtensions = extensions;
}
std::vector<FileContent*> &FilesSearcher::get_found_files(){
return mFoundFiles;
}
const char * FilesSearcher::get_home_path(){
const char *home = std::getenv(ENV_HOME);
if(home == NULL){
struct passwd *pw = getpwuid(getuid());
home = pw->pw_dir;
}
return home;
}
void FilesSearcher::parse_files(const char *base_path){
struct dirent *entry;
DIR *dir = opendir(base_path);
if(dir == NULL){
return;
}
int i = 0x0;
while((entry = readdir(dir)) != NULL){
if(strcmp(PATH_THIS, entry->d_name) != 0x0 && strcmp(PATH_PARENT, entry->d_name) != 0x0){
char *path = format_filepath(base_path, {entry->d_name});
int type = is_regular_file_or_dir(path);
if(type == IS_REGULAR_FILE){
if(check_file_ext(path)){
search_file_content((const char *) path);
}
} else {
parse_files((const char*) path);
}
free(path);
}
}
closedir(dir);
}
void FilesSearcher::search_file_content(const char *file_path){
std::string line;
std::ifstream file(file_path);
if(file.is_open()){
bool add = false;
file.seekg(0x0, std::ios_base::end);
int f_size = file.tellg();
file.seekg(0x0);
char content[f_size];
while(getline(file, line)){
for(int i = 0x0; i < mKeywords.size(); i++){
if(line.find(mKeywords[i]) != std::string::npos){
add = true;
}
}
strcat(content, line.c_str());
}
file.close();
if(add){
FileContent *fc = new FileContent((char *) file_path, get_file_ext(get_last_relative_path(file_path)), content, f_size);
mFoundFiles.push_back(fc);
}
}
}
int FilesSearcher::is_regular_file_or_dir(const char *path){
struct stat path_stat;
if(stat(path, &path_stat) != 0x0){
return 0x0;
}
return S_ISREG(path_stat.st_mode) == 0x1 ? IS_REGULAR_FILE :
S_ISDIR(path_stat.st_mode) == 0x1 ? IS_DIRECTORY : 0x0;
}
char *FilesSearcher::format_filepath(const char *base_path, const std::initializer_list<char *> &args){
char *path = new char[300];
strcpy(path, base_path);
for(char *p: args){
if(path[strlen(path) - 0x1] != '/' && p[0x0] != '/'){
char c = '/';
strncat(path, &c, 0x1);
} else if(path[strlen(path) - 0x1] == '/' && p[0x0] == '/'){
char *temp = sub_array(p, 0x1, strlen(p));
strcpy(p, temp);
free(temp);
}
strcat(path, p);
}
return path;
}
char *FilesSearcher::get_file_ext(const char *file_path){
return strrchr((char*) file_path, '.');
}
char *FilesSearcher::get_last_relative_path(const char *file_path){
return strrchr((char *) file_path, '/');
}
bool FilesSearcher::check_file_ext(const char *file_path){
char *rel = get_last_relative_path(file_path);
if(rel != NULL){
char *ext = get_file_ext(rel);
if(ext != NULL){
ext = sub_array((const char *) ext, 0x1, strlen(ext));
for(int i = 0x0; i < mExtensions.size(); i++){
if(strcasecmp(ext, mExtensions.at(i).c_str()) == 0x0){
free(ext);
return true;
}
}
free(ext);
}
}
return false;
}
char * FilesSearcher::sub_array(const char *arr, int start, int end){
char *ret = new char[end - start];
int index = 0x0;
for(int i = start; i < end; i++){
ret[index] = arr[i];
index++;
}
return ret;
}
FilesSearcher.h:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pwd.h>
#include <iostream>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fstream>
#include <vector>
#include "FileContent.h"
#define ENV_HOME "HOME"
#define LINUX_BASE_DIR_PATH "/"
#define IS_REGULAR_FILE 0x1
#define IS_DIRECTORY 0x2
#define PATH_THIS "."
#define PATH_PARENT ".."
class FilesSearcher {
public:
FilesSearcher(std::vector<std::string> keywords, std::vector<std::string> extensions);
const char * get_home_path();
void parse_files(const char *base_path);
std::vector<FileContent*> &get_found_files();
private:
std::vector<std::string> mKeywords;
std::vector<std::string> mExtensions;
std::vector<FileContent*> mFoundFiles;
void search_file_content(const char *file_path);
int is_regular_file_or_dir(const char *path);
char *format_filepath(const char *base, const std::initializer_list<char *> &rel);
char *get_file_ext(const char *file_path);
char *get_last_relative_path(const char *file_path);
bool check_file_ext(const char *file_path);
char *sub_array(const char* arr, int start, int end);
void print_dir_entry_info(dirent *entry, int num_entry);
};
FileContent.cpp:
#include "FileContent.h"
FileContent::FileContent(char *path, char *ext, char *content, int size){
mPath = new char[1000];
strcpy(mPath, path);
mExt = ext;
mContent = new char[size];
strcpy(mContent, content);
mSize = size;
}
FileContent::~FileContent(){
delete mPath;
delete mContent;
}
char *FileContent::get_path(){
return mPath;
}
char *FileContent::get_ext(){
return mExt;
}
char *FileContent::get_content(){
return mContent;
}
int FileContent::get_size(){
return mSize;
}
FileContent.h:
#include <stdio.h>
#include <string.h>
class FileContent {
private:
char *mPath;
char *mExt;
char *mContent;
int mSize;
public:
FileContent(char *path, char *ext, char *content, int size);
~FileContent();
char *get_path();
char *get_ext();
char *get_content();
int get_size();
};
- 您的代码没有像发布的那样编译。
- 您正在混合
new[]
和 free()
。
使用 -fsanitize=address
构建代码会产生:
==1926539==ERROR: AddressSanitizer: alloc-dealloc-mismatch (operator new [] vs free) on 0x6030000000a0
#0 0x7f641b887b6f in __interceptor_free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:123
#1 0x55a4e0211a4a in FilesSearcher::check_file_ext(char const*) FilesSearcher.cc:118
#2 0x55a4e0210baf in FilesSearcher::parse_files(char const*) FilesSearcher.cc:34
#3 0x55a4e0216f6a in main test_files_searcher.cc:33
#4 0x7f641b458d09 in __libc_start_main ../csu/libc-start.c:308
#5 0x55a4e02104b9 in _start (a.out+0x34b9)
0x6030000000a0 is located 0 bytes inside of 23-byte region [0x6030000000a0,0x6030000000b7)
allocated by thread T0 here:
#0 0x7f641b8897a7 in operator new[](unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:102
#1 0x55a4e0211a7b in FilesSearcher::sub_array(char const*, int, int) FilesSearcher.cc:125
#2 0x55a4e02119bf in FilesSearcher::check_file_ext(char const*) FilesSearcher.cc:111
#3 0x55a4e0210baf in FilesSearcher::parse_files(char const*) FilesSearcher.cc:34
#4 0x55a4e0216f6a in main test_files_searcher.cc:33
#5 0x7f641b458d09 in __libc_start_main ../csu/libc-start.c:308
- 将对
free()
的调用替换为 delete[]
后:
==1927190==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000113 at pc 0x7fbe6ef2ad54 bp 0x7ffc8f56c7a0 sp 0x7ffc8f56bf50
READ of size 4 at 0x602000000113 thread T0
#0 0x7fbe6ef2ad53 in __interceptor_strcasecmp ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:511
#1 0x562c2ffc8a30 in FilesSearcher::check_file_ext(char const*) FilesSearcher.cc:113
#2 0x562c2ffc7baf in FilesSearcher::parse_files(char const*) FilesSearcher.cc:34
#3 0x562c2ffc7be7 in FilesSearcher::parse_files(char const*) FilesSearcher.cc:38
#4 0x562c2ffc7be7 in FilesSearcher::parse_files(char const*) FilesSearcher.cc:38
#5 0x562c2ffcdf8c in main test_files_searcher.cc:33
#6 0x7fbe6eb1bd09 in __libc_start_main ../csu/libc-start.c:308
#7 0x562c2ffc74b9 in _start (a.out+0x34b9)
0x602000000113 is located 0 bytes to the right of 3-byte region [0x602000000110,0x602000000113)
allocated by thread T0 here:
#0 0x7fbe6ef4c7a7 in operator new[](unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:102
#1 0x562c2ffc8a9d in FilesSearcher::sub_array(char const*, int, int) FilesSearcher.cc:125
#2 0x562c2ffc89d3 in FilesSearcher::check_file_ext(char const*) FilesSearcher.cc:111
#3 0x562c2ffc7baf in FilesSearcher::parse_files(char const*) FilesSearcher.cc:34
#4 0x562c2ffc7be7 in FilesSearcher::parse_files(char const*) FilesSearcher.cc:38
#5 0x562c2ffc7be7 in FilesSearcher::parse_files(char const*) FilesSearcher.cc:38
#6 0x562c2ffcdf8c in main test_files_searcher.cc:33
#7 0x7fbe6eb1bd09 in __libc_start_main ../csu/libc-start.c:308
这是因为您没有 NUL
-终止您在 sub_array
中创建的字符串。解决这个问题,最终生成一个没有显示 AddressSanitizer 错误并且不会崩溃的程序。
TL;DR:使用 AddressSanitizer。此外,如果您使用 std::string
而不是对 C 风格的字符串进行操作,此程序会更简单。
我写了一个简单的程序,可以在文件中搜索特定的文本,但是我得到了这个错误:
Program received signal SIGSEGV, Segmentation fault
.
你能告诉我我错在哪里吗?你能告诉我如何使用 GDB 调试器来获取有关我遇到的错误的信息吗?
(使用 GDB 我得到这个错误:
Program received signal SIGSEGV, Segmentation fault.
0x0000555555557612 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::size() const ()
但我不知道如何获得有关该错误的更多信息,您能解释一下吗?
代码测试程序:
/**
COMPILATION:
g++ test_files_searcher.cpp -o files_searcher.out FilesSearcher_Linux/FilesSearcher.cpp FilesSearcher_Linux/FileContent.cpp
**/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pwd.h>
#include <iostream>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fstream>
#include <vector>
#include "FilesSearcher_Linux/FilesSearcher.h"
#define SIZE_SEARCH_MATRIX 0x6
#define SIZE_EXTS_ARRAY 0x1
int main(){
using namespace std;
std::vector<std::string> matrix = {"test[=11=]", "lol[=11=]", "asd[=11=]", "lmao[=11=]", "rotfl[=11=]"};
std::vector<std::string> exts = {"txt[=11=]"};
FilesSearcher fs = FilesSearcher(matrix, exts);
const char *home_path = fs.get_home_path();
cout << "[+] Home Path: " << home_path << endl;
fs.parse_files(home_path);
if(fs.get_found_files().size() > 0x0){
for(FileContent *fc : fs.get_found_files()){
std::cout << "file path == " << fc->get_path() << " file content == " << fc->get_content() << std::endl;
delete fc;
}
}
}
FilesSearcher.cpp:
#include "FilesSearcher.h"
FilesSearcher::FilesSearcher(std::vector<std::string> keywords, std::vector<std::string> extensions){
mKeywords = keywords;
mExtensions = extensions;
}
std::vector<FileContent*> &FilesSearcher::get_found_files(){
return mFoundFiles;
}
const char * FilesSearcher::get_home_path(){
const char *home = std::getenv(ENV_HOME);
if(home == NULL){
struct passwd *pw = getpwuid(getuid());
home = pw->pw_dir;
}
return home;
}
void FilesSearcher::parse_files(const char *base_path){
struct dirent *entry;
DIR *dir = opendir(base_path);
if(dir == NULL){
return;
}
int i = 0x0;
while((entry = readdir(dir)) != NULL){
if(strcmp(PATH_THIS, entry->d_name) != 0x0 && strcmp(PATH_PARENT, entry->d_name) != 0x0){
char *path = format_filepath(base_path, {entry->d_name});
int type = is_regular_file_or_dir(path);
if(type == IS_REGULAR_FILE){
if(check_file_ext(path)){
search_file_content((const char *) path);
}
} else {
parse_files((const char*) path);
}
free(path);
}
}
closedir(dir);
}
void FilesSearcher::search_file_content(const char *file_path){
std::string line;
std::ifstream file(file_path);
if(file.is_open()){
bool add = false;
file.seekg(0x0, std::ios_base::end);
int f_size = file.tellg();
file.seekg(0x0);
char content[f_size];
while(getline(file, line)){
for(int i = 0x0; i < mKeywords.size(); i++){
if(line.find(mKeywords[i]) != std::string::npos){
add = true;
}
}
strcat(content, line.c_str());
}
file.close();
if(add){
FileContent *fc = new FileContent((char *) file_path, get_file_ext(get_last_relative_path(file_path)), content, f_size);
mFoundFiles.push_back(fc);
}
}
}
int FilesSearcher::is_regular_file_or_dir(const char *path){
struct stat path_stat;
if(stat(path, &path_stat) != 0x0){
return 0x0;
}
return S_ISREG(path_stat.st_mode) == 0x1 ? IS_REGULAR_FILE :
S_ISDIR(path_stat.st_mode) == 0x1 ? IS_DIRECTORY : 0x0;
}
char *FilesSearcher::format_filepath(const char *base_path, const std::initializer_list<char *> &args){
char *path = new char[300];
strcpy(path, base_path);
for(char *p: args){
if(path[strlen(path) - 0x1] != '/' && p[0x0] != '/'){
char c = '/';
strncat(path, &c, 0x1);
} else if(path[strlen(path) - 0x1] == '/' && p[0x0] == '/'){
char *temp = sub_array(p, 0x1, strlen(p));
strcpy(p, temp);
free(temp);
}
strcat(path, p);
}
return path;
}
char *FilesSearcher::get_file_ext(const char *file_path){
return strrchr((char*) file_path, '.');
}
char *FilesSearcher::get_last_relative_path(const char *file_path){
return strrchr((char *) file_path, '/');
}
bool FilesSearcher::check_file_ext(const char *file_path){
char *rel = get_last_relative_path(file_path);
if(rel != NULL){
char *ext = get_file_ext(rel);
if(ext != NULL){
ext = sub_array((const char *) ext, 0x1, strlen(ext));
for(int i = 0x0; i < mExtensions.size(); i++){
if(strcasecmp(ext, mExtensions.at(i).c_str()) == 0x0){
free(ext);
return true;
}
}
free(ext);
}
}
return false;
}
char * FilesSearcher::sub_array(const char *arr, int start, int end){
char *ret = new char[end - start];
int index = 0x0;
for(int i = start; i < end; i++){
ret[index] = arr[i];
index++;
}
return ret;
}
FilesSearcher.h:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pwd.h>
#include <iostream>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fstream>
#include <vector>
#include "FileContent.h"
#define ENV_HOME "HOME"
#define LINUX_BASE_DIR_PATH "/"
#define IS_REGULAR_FILE 0x1
#define IS_DIRECTORY 0x2
#define PATH_THIS "."
#define PATH_PARENT ".."
class FilesSearcher {
public:
FilesSearcher(std::vector<std::string> keywords, std::vector<std::string> extensions);
const char * get_home_path();
void parse_files(const char *base_path);
std::vector<FileContent*> &get_found_files();
private:
std::vector<std::string> mKeywords;
std::vector<std::string> mExtensions;
std::vector<FileContent*> mFoundFiles;
void search_file_content(const char *file_path);
int is_regular_file_or_dir(const char *path);
char *format_filepath(const char *base, const std::initializer_list<char *> &rel);
char *get_file_ext(const char *file_path);
char *get_last_relative_path(const char *file_path);
bool check_file_ext(const char *file_path);
char *sub_array(const char* arr, int start, int end);
void print_dir_entry_info(dirent *entry, int num_entry);
};
FileContent.cpp:
#include "FileContent.h"
FileContent::FileContent(char *path, char *ext, char *content, int size){
mPath = new char[1000];
strcpy(mPath, path);
mExt = ext;
mContent = new char[size];
strcpy(mContent, content);
mSize = size;
}
FileContent::~FileContent(){
delete mPath;
delete mContent;
}
char *FileContent::get_path(){
return mPath;
}
char *FileContent::get_ext(){
return mExt;
}
char *FileContent::get_content(){
return mContent;
}
int FileContent::get_size(){
return mSize;
}
FileContent.h:
#include <stdio.h>
#include <string.h>
class FileContent {
private:
char *mPath;
char *mExt;
char *mContent;
int mSize;
public:
FileContent(char *path, char *ext, char *content, int size);
~FileContent();
char *get_path();
char *get_ext();
char *get_content();
int get_size();
};
- 您的代码没有像发布的那样编译。
- 您正在混合
new[]
和free()
。
使用-fsanitize=address
构建代码会产生:
==1926539==ERROR: AddressSanitizer: alloc-dealloc-mismatch (operator new [] vs free) on 0x6030000000a0
#0 0x7f641b887b6f in __interceptor_free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:123
#1 0x55a4e0211a4a in FilesSearcher::check_file_ext(char const*) FilesSearcher.cc:118
#2 0x55a4e0210baf in FilesSearcher::parse_files(char const*) FilesSearcher.cc:34
#3 0x55a4e0216f6a in main test_files_searcher.cc:33
#4 0x7f641b458d09 in __libc_start_main ../csu/libc-start.c:308
#5 0x55a4e02104b9 in _start (a.out+0x34b9)
0x6030000000a0 is located 0 bytes inside of 23-byte region [0x6030000000a0,0x6030000000b7)
allocated by thread T0 here:
#0 0x7f641b8897a7 in operator new[](unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:102
#1 0x55a4e0211a7b in FilesSearcher::sub_array(char const*, int, int) FilesSearcher.cc:125
#2 0x55a4e02119bf in FilesSearcher::check_file_ext(char const*) FilesSearcher.cc:111
#3 0x55a4e0210baf in FilesSearcher::parse_files(char const*) FilesSearcher.cc:34
#4 0x55a4e0216f6a in main test_files_searcher.cc:33
#5 0x7f641b458d09 in __libc_start_main ../csu/libc-start.c:308
- 将对
free()
的调用替换为delete[]
后:
==1927190==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000113 at pc 0x7fbe6ef2ad54 bp 0x7ffc8f56c7a0 sp 0x7ffc8f56bf50
READ of size 4 at 0x602000000113 thread T0
#0 0x7fbe6ef2ad53 in __interceptor_strcasecmp ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:511
#1 0x562c2ffc8a30 in FilesSearcher::check_file_ext(char const*) FilesSearcher.cc:113
#2 0x562c2ffc7baf in FilesSearcher::parse_files(char const*) FilesSearcher.cc:34
#3 0x562c2ffc7be7 in FilesSearcher::parse_files(char const*) FilesSearcher.cc:38
#4 0x562c2ffc7be7 in FilesSearcher::parse_files(char const*) FilesSearcher.cc:38
#5 0x562c2ffcdf8c in main test_files_searcher.cc:33
#6 0x7fbe6eb1bd09 in __libc_start_main ../csu/libc-start.c:308
#7 0x562c2ffc74b9 in _start (a.out+0x34b9)
0x602000000113 is located 0 bytes to the right of 3-byte region [0x602000000110,0x602000000113)
allocated by thread T0 here:
#0 0x7fbe6ef4c7a7 in operator new[](unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:102
#1 0x562c2ffc8a9d in FilesSearcher::sub_array(char const*, int, int) FilesSearcher.cc:125
#2 0x562c2ffc89d3 in FilesSearcher::check_file_ext(char const*) FilesSearcher.cc:111
#3 0x562c2ffc7baf in FilesSearcher::parse_files(char const*) FilesSearcher.cc:34
#4 0x562c2ffc7be7 in FilesSearcher::parse_files(char const*) FilesSearcher.cc:38
#5 0x562c2ffc7be7 in FilesSearcher::parse_files(char const*) FilesSearcher.cc:38
#6 0x562c2ffcdf8c in main test_files_searcher.cc:33
#7 0x7fbe6eb1bd09 in __libc_start_main ../csu/libc-start.c:308
这是因为您没有 NUL
-终止您在 sub_array
中创建的字符串。解决这个问题,最终生成一个没有显示 AddressSanitizer 错误并且不会崩溃的程序。
TL;DR:使用 AddressSanitizer。此外,如果您使用 std::string
而不是对 C 风格的字符串进行操作,此程序会更简单。