我正在制作的大型程序的一部分需要从命令行读入并存储在类中的路径。因为路径可以是任意大小,并且在多个函数中需要它,所以我将它存储在头文件中的char*
中。但是,出于某种原因,当我为它分配一个值时,程序会出现段错误。
调试器(gdb)显示以下内容:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b4828a in std::basic_istream<char, std::char_traits<char> >& std::operator>><char, std::char_traits<char> >(std::basic_istream<char, std::char_traits<char> >&, char*) ()
from /usr/lib/libstdc++.so.6
这是我写的用来演示问题的程序:
TEST.CPP:
#include "test.h"
#include <iostream>
#include <cstring>
Test::Test() {
filepath = NULL;
}
void Test::set_path(char* string) {
char temp[strlen(string) + 1];
strcpy(filepath, temp);
}
char * Test::get_path() {
return filepath;
}
int main(int argc, char *argv[]) {
std::cout << "Enter a file path: ";
char *temp;
std::cin >> temp;
Test *temp2 = new Test();
temp2->set_path(temp);
std::cout << "Path: " << temp2->get_path() << std::endl;
}
test.h:
#ifndef TEST_H
#define TEST_H
class Test {
private:
char *filepath;
public:
Test();
void set_path(char *);
char * get_path();
};
#endif // TEST_H
我不确定它崩溃的原因。我正在做这个方法有什么问题吗?此外,我不想只切换到string
,而是想了解更多有关此问题的信息。
提前致谢!
答案 0 :(得分:3)
temp
(在main
内)未初始化且未指向任何有效的已分配内存块,因此行:
std::cin >> temp;
导致输入被写入内存的某个未知部分,导致未定义的行为。你应该:
temp
成为char[]
,只读取适合缓冲区的字符数。temp
指向有效的缓冲区。temp
设为std::string
,让std::string
课程担心内存管理问题。
解决上述问题后,您还会遇到与filePath
类似的问题。在filePath
构造函数中,NULL
被设置为Test
,然后您将temp
复制到filePath
指向Test::set_path
的内存块中{1}}:
strcpy(filepath, temp);
NULL
指的是您不允许取消引用的地址。您应该将所有C字符串更改为std::string
并使用std::string
成员函数和重载运算符来处理C ++中的字符串。
答案 1 :(得分:1)
您调用strcpy
而不为set_path
中要复制的字符串分配内存。手册页明确指出dest
必须足够大才能包含src
中的字符串。除了你从一个空的临时复制。虽然,当您从cin
读取未初始化的指针时,您的崩溃会提前出现。
使用std::string
。
#include <iostream>
class Foo
{
public:
Foo(const std::string& s) : s_(s) {} ;
private:
std::string s_;
};
int main()
{
std::string f;
std::cin >> f;
std::cout << f << std::endl;
Foo foo = Foo(f);
return 0;
}
如果你确实喜欢你在做什么:
class Foo
{
public:
Foo(const char* s) {
size_t size = strlen(s);
s_ = new char[size + 1];
// safer
strncpy(s_, s, size + 1);
} ;
private:
char* s_;
};
int main()
{
char buffer[1024];
// be save
buffer[1023] = '\0';
Foo foo = Foo(buffer);
return 0;
}
第二个例子仍然破裂。它缺少一个正确的析构函数,复制构造函数和赋值运算符。我会留下这个练习。
答案 2 :(得分:0)
Test::Test() {
filepath = NULL;
}
void Test::set_path(char* string) {
char temp[strlen(string) + 1];
strcpy(filepath, temp);
}
我不确定你认为strcpy
将要做什么,但它做的是将temp
(未初始化)复制到filepath
,这是NULL。所以这两个参数都没有任何意义。