2012-08-03 55 views
0

我正在使用一些遺留代碼。在以下情況下,舊版代碼在生產模式下工作。我正在嘗試構建用於測試目的的舊版代碼的命令行版本。我懷疑這裏有一個環境設置問題,但我對C++和Visual Studio相當陌生(很長一段時間的eclipse/java人)。在Visual Studio 2005中使用string :: iterator的空指針問題

此代碼嘗試從流中讀取字符串。它讀取一個簡短的內容,在我的調試場景中它的值爲11.然後,它應該讀取11個字符。但是這個代碼在第一個字符上出現了。具體而言,在下面的read方法中,ptr爲空,因此fread調用將引發異常。爲什麼ptr爲NULL?

要澄清一點,ptr在操作符>>(字符串)和操作符>>(char)之間變爲空值。

Mystream& Mystream::operator>>(string& str) 
{ 
string::iterator    it; 
short       length; 

*this >> length; 

if(length >= 0) 
{ 
    str.resize(length); 
    for (it = str.begin(); it != str.end(); ++it) 
    { 
     *this >> *it; 
    } 
} 

return *this; 
} 

閱讀短的方法是在這裏,看着文件緩衝區等,這看起來像它正常工作。現在

Mystream& Mystream::operator>>(short& n) 
{ 
    read((char*)&n, sizeof(n)); 
    SwapBytes(*this, (char*)&n, sizeof(n)); 
    return *this; 
} 

,在一個char讀取的方法是在這裏:

Mystream& Mystream::operator>>(char& n) 
{ 
    read((char*)&n, sizeof(n)); 
    return *this; 
} 

和讀取方法是:

Mystream& Mystream::read(char* ptr, int n) 
{ 
fread((void*)ptr, (size_t)1, (size_t)n, fp); 
return *this; 
} 

有一件事我不明白,在字符串中輸入法,*它是一個char對嗎?那麼爲什麼操作員>>(char & n)方法在該行被派遣?在調試器中,它看起來像*它是0(儘管一個同事告訴我他不信任2005年的調試器),因此,它看起來像是& n被視爲空指針,所以讀取方法拋出異常。

您可以提供的任何見解將是最有幫助的!

感謝 約翰

PS。對於好奇,Swap字節看起來是這樣的:

inline void SwapBytes(Mystream& bfs, char * ptr, int nbyte, int nelem = 1) 
{ 
    // do we need to swap bytes? 
if(bfs.byteOrder() != SYSBYTEORDER) 
    DoSwapBytesReally(bfs, ptr, nbyte, nelem); 
} 

而且DoSwapBytesReally樣子:

void DoSwapBytesReally(Mystream& bfs, char * ptr, int nbyte, int nelem) 
{ 
    // if the byte order of the file 
    // does not match the system byte order 
    // then the bytes should be swapped 
int i, n; 
char temp; 

#ifndef _DOSPOINTERS_ 
char *ptr1, *ptr2; 
#else _DOSPOINTERS_ 
char huge *ptr1, huge *ptr2; 
#endif _DOSPOINTERS_ 

int nbyte2; 

nbyte2 = nbyte/2; 

for (n = 0; n < nelem; n++) 
{ 
    ptr1 = ptr; 
    ptr2 = ptr1 + nbyte - 1; 

    for (i = 0; i < nbyte2; i++) 
    { 
     temp = *ptr1; 
     *ptr1++ = *ptr2; 
     *ptr2-- = temp; 
    } 

    ptr += nbyte; 
} 
} 
+0

哪裏讀取short的方法? – ForEveR 2012-08-03 15:34:34

+0

更新後的描述。 – John 2012-08-03 15:56:54

+0

你似乎相信'char&n'的語法與指針有某種關係。事實並非如此。它聲明瞭一個參考。它被綁定到'char'對象'* it',因爲它應該。閱讀您最喜愛的C++書籍中的參考資料。 – AnT 2012-08-03 16:00:29

回答

2

我拋出這個爛攤子,並開始了。從代碼推斷,如果你有實際工作,這將是大致相當於是這樣的:

MyStream::operator>>(string &s) { 
    short size; 

    fread((void *)&size, sizeof(size), 1, fP); 
    size = ntohs(size); // oops: after reading edited question, this is really wrong. 
    s.resize(size); 
    fread((void *)&s[0], 1, size, fp); 
    return *this; 
} 

在這種情況下,委託大部分工作等功能似乎並沒有太多上漲 - - 這可以更直接地完成這項工作,但仍然不會比原來的更長或更復雜(如果有的話,我會說相反)。

+0

當字符串長度爲零時,'&s [0]'無效。 – john 2012-08-03 16:20:04

+0

+1贊同層​​似乎有一個overfondness。 – 2012-08-03 16:23:10

+0

@john:是的,這是假定所有序列化的字符串都是非零長度。當然,我們還不能確定事情的真相 - 事實上,從代碼的角度來看,我猜想那些早在幾年前就已經忘記的人們(DOS指針?真的?) – 2012-08-03 16:24:20

0

我在公司裏發現了一個灰色的鬍鬚,他可以解釋發生在我身上的事情。 (我已經和2個老計時器說過話了,所以我想我已經覆蓋了老計時器的攻擊途徑)。上面的代碼不是ANSI兼容的STL代碼。在Visual Studio 2005中,Microsoft首次引入了STL,並且存在問題。特別是過去工作的舊代碼在2005年現在會失敗(我認爲64位模式也可能在這方面發揮作用。)因此,代碼將不能在調試模式下工作(但它將在發佈模式下工作)。一篇文章位於此處。 http://msdn.microsoft.com/en-us/library/aa985982%28v=vs.80%29.aspx

我看到的特定問題與問題中第一種方法中的行:it = str.begin()有關。 str是一個空字符串。所以str.begin()在技術上沒有定義。 Visual Studio在調試和發佈模式之間以不同的方式處理這種情況。 (不能在調試中做到這一點,你可以在發佈中做到這一點。)

底線,灰鬍子建議重寫是正確的傑裏的。具有諷刺意味的是,灰鬍子已經在幾個文件中解決了這個問題,但忽略了將其檢入主線。呃哦。這嚇倒了&#$!在我之外。