2011-12-25 101 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。所以這兩個參數都沒有意義。