2011-12-25 100 views
0

我正在制作的更大程序的一部分需要从命令行读入并存储在类中。因为路径可以是任意大小,并且需要多个函数,所以我将它存储在头文件中的char*中。但是,由于某种原因,当我给它赋值时,程序会出现段错误。C++全局字符指针?

调试器(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

“而不是只是切换到'字符串',我想了解更多关于这个问题。”为什么,你对'串'过敏? – 2011-12-25 04:54:22

+0

我最终使用'std :: string''。我只是想弄清楚为什么'char *'不起作用。 – 2011-12-26 02:52:07

回答

3

temp(内侧main)是未初始化的,而不是指向的存储器中的任何有效的分配块,因此该行:

std::cin >> temp; 

导致输入要写入到存储器的某个未知部分,造成未定义的行为。你应该:

  • temp一个char[],只有在将适合在缓冲区的字符量读取。
  • 将点temp转换为有效的缓冲区。
  • 更好的是,使和std::string,并让std::string类担心内存管理。


你也要去你解决上述问题后要具有filePath类似的问题。 filePath被设置为NULLTest构造函数,然后你复制temp到内存filePathTest::set_path指出块:

strcpy(filepath, temp); 

NULL指的是你不能解引用的地址。您应该将所有C字符串更改为std::string s,并使用std::string成员函数和重载运算符来处理C++中的字符串。

+0

所以解决的办法是使'char'是一个固定大小(如FILENAME_MAX)或使用'std :: string'? – 2011-12-25 03:43:12

+0

@ ChenXiao-Long:在C++中,'std :: string'。 – AusCBloke 2011-12-25 03:45:45

+0

好的,我将使用'std :: string'。谢谢你的回答! – 2011-12-25 03:52:13

1

您在不为set_path中的字符串分配内存的情况下调用strcpy。手册页明确指出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; 
} 

如果你真的preffer你在做什么:

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; 
} 

第二个例子仍然是断开的。它缺少一个合适的析构函数,复制构造函数和赋值运算符。我将此作为练习。

+0

谢谢你的回答!我可能会坚持使用'std :: string',但我一定会看看你的第二个方法作为练习。 – 2011-12-25 03:55:42

0
Test::Test() { 
    filepath = NULL; 
} 

void Test::set_path(char* string) { 
    char temp[strlen(string) + 1]; 
    strcpy(filepath, temp); 
} 

我不知道你想什么strcpy打算做些什么,而它的作用是从temp复制,这是未初始化,以filepath,这是NULL。所以这两个参数都没有意义。