2016-01-09 51 views
0

我一直在嘗試學習一些關於C++中的套接字編程的知識,因此一直在開發基本的IRC bot。我有它連接和工作,但我有一個問題,確定誰加入了通道(即是機器人本身,隨機用戶或我的JOIN命令)。變量賦值重寫其他變量的值

我使用的克利翁在Windows 7

我有下面的代碼:

//determine if message is JOIN command 
if(regex_search(line, match, std::regex(R"(:([^!]*)!.*?JOIN)"))) 
{ 
    //get the nickname of the bot (details.getNickName() shown in next code segment) 
    const char *trueNick = details.getNickName(); 
    //reformat nickname because the following is returned from the method alone 
    //0x10042d0f9 <_ZStL6ignore+119> "CPlusPlusBotTest" 
    const char *nick = string(details.getNickName()).c_str(); 
    //get the name of the user who joined 
    const char *name = match.str(1).c_str(); 
    //debugging 
    std::cout << name << " - name\n"; 
    std::cout << nick << " - nick\n"; 
    //might not be the correct way to compare the two? but I'll sort that out later 
    if(name != nick) 
    { 
     //welcome the user 
     char param[1024]; 
     sprintf(param, "%s :Hello, %s", details.getChannel(), name); 
     sendData("PRIVMSG", param); 
    } 
} 

我不確定爲什麼我得到的多餘的「東西」(我不知道它是什麼是)從我的吸氣劑,因爲它是簡單地回送一個專用變量的情況下:

const char* BotDetails::getNickName() { return nickName; } 

無論如何,這不是給我可以擺脫它在我的問題(儘管它可能是相當哈克)。

我的問題是,當我連接到測試通道,和我在該行指定trueNick,所以我可以看到我通過程序步驟發生了什麼斷點,會出現以下情況:

1) trueNick被分配值:0x10042d0f9 < _ZStL6ignore + 119> 「CPlusPlusBotTest」

2)切口的值指定爲: 「CPlusPlusBotTest」

3)名稱被分配的值: 「Seanharrs」 和切口被分配了價值:「Seanharrs」

這意味着當我的調試語句運行時,nick和name是相同的值。我不確定爲什麼nick被重新分配爲與name相同的值,這不應該發生。它每次都發生,不僅僅是爲了我的名字。我嘗試使用char數組和字符串,但無濟於事。我也發現奇怪的是,trueNick從不受影響,它只是這兩個變量。任何幫助都是值得讚賞的(即使它只是一種更好的方法來檢查這個問題而不是解決方法,因爲在我的最終結果中,沒有人會遇到這種情況)。

+0

你有一些東西類似於常見的字符串流問題發生:http://stackoverflow.com/questions/1374468/stringstream-string-and-char-conversion-confusion – chris

+2

停止使用'char *'s,並使用改爲使用'std :: string'。這將自動解決您的許多問題。 – Mat

+3

'const char * nick = string(details.getNickName())。c_str();'不會使用'nick'是UB? –

回答

2

這行導致未定義的行爲:

const char *nick = string(details.getNickName()).c_str(); 

將構造一個臨時字符串對象,並返回一個指針的數據。然而,暫時的意味着它會立即被破壞,指針將會失效。

編輯:

原來OP誤解由調試器所顯示的附加信息並解釋其作爲變量的值。澄清後,就沒有必要爲「轉化率」這導致未定義的行爲和所述代碼可以只是:

const char *nick = details.getNickName(); 
const char *name = match.str(1).c_str(); 
if(strcmp(name, nick) == 0) 
{ 
    //.... 
} 

的未定義的行爲的例子仍如下所示。FOR THE未定義行爲

示例代碼考慮以下代碼:

#include <iostream> 
using namespace std; 

int main() { 
    const char t[] = "0x10042d0f9 <_ZStL6ignore+119> \"CPlusPlusBotTest\""; 
    const char* pTrue = t; 
    const char* p = std::string(t).c_str(); 
    std::cout << pTrue << std::endl; 
    std::cout << p << std::endl; 
    return 0; 
} 

它將輸出(而:它可以輸出):

0x10042d0f9 <_ZStL6ignore+119> "CPlusPlusBotTest" 
0x10042d0f9 <_ZStL6ignore+119> "CPlusPlusBotTest" 

(ideone.com使用對於這個例子並給出以上輸出)

所以從這個你可能會認爲它是好的。 (但請注意:我沒有得到OP提到的轉換)。

現在考慮這樣的代碼:

#include <iostream> 
using namespace std; 

int main() { 
    const char tdemo[] = "Some demo text"; // Added this line 
    const char t[] = "0x10042d0f9 <_ZStL6ignore+119> \"CPlusPlusBotTest\""; 
    const char* pTrue = t; 
    const char* p = std::string(t).c_str(); 
    const char* pdemo = std::string(tdemo).c_str(); // Added this line 
    std::cout << pTrue << std::endl; 
    std::cout << p << std::endl; 
    return 0; 
} 

它將輸出(而:它可以輸出)

0x10042d0f9 <_ZStL6ignore+119> "CPlusPlusBotTest" 
Some demo text 

(ideone.com用於該實施例和上述輸出給)

正如你可以看到* p的值意外地改變了。它改變了,因爲指針指向已釋放的內存,因此指針無效。額外的行

const char* pdemo = std::string(tdemo).c_str(); 

導致編譯器重新使用該內存並因此更改值* p。

換句話說 - 你有未定義的行爲。

我的猜測是,你的問題是內部details.getNickName();

在我看來,返回的指針是不是每次都指向同一個測試。也許它有一些初始化問題,以便它在第一次返回錯誤的值,然後修正值。

導致未定義行爲的行不能執行OP聲明的轉換,因此它必須是來自更改函數的返回值。

+0

這很有道理,謝謝。我現在看到爲什麼它很麻煩,並且將來會避免使用這種方法。仍然沒有解釋爲什麼'0x10042d0f9 <_ZStL6ignore + 119>'存在於'string'變量之外,儘管(它沒有出現在std :: cout << trueNick;但是它在調試器中看到trueNick的值時出現,它位於「字符串」的「外部」,但仍然影響其值,因此它被認爲與「CPlusPlusBotTest」不同,即使TrueNick的唯一'字符串'部分是「CPlusPlusBotTest」) – Seanharrs

+0

@Seanharrs - 閱讀我的評論題。 '0x10042d0f9 <_ZStL6ignore + 119>'不存在!這只是調試器顯示的一些附加信息。它與字符串的值無關。 – 4386427

+0

我認爲這將是與該字符串的值無關的「額外」信息,但它似乎會更改該值,因爲「CPlusPlusBotTest」與CPlusPlusBotTest被認爲是不同的「0x10042d0f9 <_ZStL6ignore + 119>」 。不過,我認爲這只是因爲我在比較'=='。再次感謝。 :)我沒有接受,因爲我找不到按鈕:P我現在有。 – Seanharrs