2015-12-04 95 views
0

我想將字符指針傳遞給函數,它將在內部使用字符串read_json。但是在函數出來之後,指針的內容就會發生變化。以下是代碼。爲什麼const char *不能與stringstream和read_json一起工作?

string tempstr; 
void someFunc() 
{ 
    const char *ptr = getDiagnosticGroupValue("Device.ManagementServer"); 
    printf("string : %s\n", getParameterValue(ptr, "URL")); 
    printf("string : %s\n", getParameterValue(ptr, "Username")); 
} 
const char* getParameterValue(const char *jsonstring, const char* param) 
{ 
    return getString(jsonstring, param); 
} 
const char* getString(const char *jsonstring, const char* param) 
{ 
    stringstream jsonstringstream; 
    jsonstringstream << jsonstring; 

    string paramstr(param); 

    try 
    { 
     boost::property_tree::ptree pt; 
     boost::property_tree::read_json(jsonstringstream, pt); 
     tempstr = pt.get<string>(paramstr); 
     return tempstr.c_str(); 
    } 
    catch(...) 
    { 
     jsonstringstream.clear(); 
     jsonstringstream.str(""); 
     cout << "Node Doesn't exist" << endl; 
     return "N/A"; 
    } 
} 

對於第一個節點(URL),它返回正確的值,我可以在someFunc()中打印字符串。但是ptr內容正在被修改(並且它不再是json格式字符串)。所以第二次,當調用getParameterValue()時,read_json拋出異常說不是json格式。我想知道爲什麼即使我聲明爲const char * ptr,ptr內容也得到了改變。任何人都可以讓我知道如何解決這個問題。

我確認問題不在於臨時對象。我通過創建全局字符串並從全局字符串返回char *來修改代碼。但我面臨同樣的問題。還有一件事情是,當第一次調用getParameterValue()時,我在read_json()之後放置print語句來檢查ptr的值,並且ptr已經被該時間破壞了。

getDiagnosticGrouapValue()的實現如下。

const char* getDiagnosticGroupValue(const char* group) 
{ 
    VZUAL& vzual = VZUAL::getInstance(); 

    string groupStr(group, group + strlen(group)); 
    return vzual.Diagnostics.getGroupValue(groupStr).c_str(); 
} 

const string PlatformDiagnostics::getGroupValue(const string& _groupName_, const string& DUMMY) 
{ 
    boost::property_tree::ptree ptRead; 
    boost::property_tree::ptree ptWrite; 
    string path = _groupName_ + "."; 
    stringstream ss; 

    try { 
     boost::property_tree::read_json(Resource::diagnosticsFile.c_str(), ptRead); 
    } 
    catch (boost::property_tree::json_parser::json_parser_error &je) { 
     return Resource::defaultValue; 
    } 

    try { 
     BOOST_FOREACH(boost::property_tree::ptree::value_type &v, ptRead.get_child(path)) 
     ptWrite.put(v.first.data(), v.second.data()); 
    } 
    catch (...) { 
    return Resource::defaultValue; 
    } 

    boost::property_tree::write_json(ss, ptWrite); 
    return ss.str(); 
} 
+0

請不要用[tag:c]標記此問題。 –

回答

2

您正在返回指向在堆棧上創建的字符串的指針,在getString函數內部。這是未定義的行爲。

從您的代碼,所有的變量:

string paramstr(param); 
boost::property_tree::ptree pt; 
boost::property_tree::read_json(jsonstringstream, pt); 
return (pt.get<string>(paramstr)).c_str(); 

表明,該字符串不是靜態或全球範圍內創建。

如果你正在返回一個指向jsonstring某個部分的指針,你可能應該在jsonstring中找到這個字符串並返回指向它的指針。問題是它不會被空終止(所以你需要返回長度)。

其他解決方案是爲getString提供一個將從getString返回的char數組。但是你必須確保它足夠大,並且它太小,然後返回NULL,以便客戶端代碼可以提供更大的緩衝區。

+0

我確認問題不在於臨時對象。我通過創建全局字符串並從全局字符串返回char *來修改代碼。但我面臨同樣的問題。還有一件事情是,當第一次調用getParameterValue()時,我在read_json()之後放置print語句來檢查ptr的值,並且ptr已經被該時間破壞了。 – kadina

+1

@kadina它是const char *,所以很難相信它會被修改,也可以放在stringstream裏面,這肯定不會改變它。也許在這個JSON中沒有'用戶名'? '問題不在於臨時對象' - 事實並非如此,你只有一個以上的問題:-)直到你嘗試從多個線程使用你的函數,或者嘗試在某處存儲返回值時,你現在使用全局變量的解決方案是OK的。 – marcinj

+0

用戶名存在於json字符串中。我用參數「Username」去掉了getString()的調用,而是在someFunc()中的getString()後面打印ptr,並打印損壞的字符串。 – kadina

相關問題