2017-04-11 154 views
1

我嘗試做一些簡單的事情:我有2個函數,第一個生成2個char數組,然後1個int然後連接它們,reinterpret_cast作爲void*並返回它。使用reinterpret_cast序列化和反序列化數據

第二個將它重新解釋爲char*並打印出來。 問題是:如果我將它重新解釋爲char*並在void*強制轉換之後打印它(在同一函數中),但它運行良好,但不在反序列化函數中。

這裏是我的代碼:

#include <sstream> 
#include <unistd.h> 

void * serialize(void) 
{ 
    char s1[9]; 
    char s2[9]; 
    int n; 
    std::string alphanum = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 

    s1[8] = '\0'; 
    s2[8] = '\0'; 

    for (int i = 0; i < 8; i++) 
    { 
     usleep(1); 
     s1[i] = alphanum[clock() % (alphanum.length() - 1)]; 
    } 
    n = clock() % 2147483647; 
    for (int i = 0; i < 8; i++) 
    { 
     usleep(1); 
     s2[i] = alphanum[clock() % (alphanum.length() - 1)]; 
    } 

    std::cout << "s1: " << s1 << std::endl; 
    std::cout << "n: " << n << std::endl; 
    std::cout << "s2: " << s2 << std::endl; 

    std::stringstream ss; 
    std::string str; 
    ss << s1 << n << s2; 
    ss >> str; 

    char * c = const_cast<char*>(str.c_str()); 
    void * d = reinterpret_cast<void*>(c); 
    std::cout << reinterpret_cast<char*>(d) << std::endl; // HERE IT WORKS 
    return d; 
} 

void deserialize(void * raw) 
{ 
    char* c = reinterpret_cast<char*>(raw); 
    std::cout << c << std::endl; //HERE IT DOESN'T WORK 
} 

int  main(void) 
{ 
    void* serialized = serialize(); 
    deserialize(serialized); 

    return 0; 
} 

我的輸出看起來像:

s1: 6dfhkmoq n: 1857 s2: tyADFHKM 6dfhkmoq1857tyADFHKM 6�c2X� d2X�

我該怎麼做纔能有相同的輸出?

+1

變量str是棧上的類型,你實際上是返回一個指向其內部緩衝。只要你在序列化函數中,一切都沒問題(str仍然存在),但是一旦你離開serialize函數,str變量就會被釋放,你現在正在訪問被釋放的內存,你可以期望的最好的內存是垃圾 – gastush

+0

哦,是的,當我將它分配到堆上時它會更好,謝謝。 – LeCintas

回答

1

這是因爲你正在返回一個指向內存的string對象(帶自動存儲)。從cppeference

返回值

指針到基礎字符的存儲。

當堆棧展開時,爲字符串分配的內存會被覆蓋(以及內部緩衝區)。當塊由於例外或者到達控制流程結束時結束時發生。

閱讀What is stack unwinding?

爲了確保您的存儲位置仍然是有效的,你將不得不將它分配在堆上。您可以創建shared_ptr並返回。

但是往往reinterpret_cast聞起來像不好的設計,所以你可能要重新考慮你爲什麼要躲在一個void*