2016-11-17 48 views
0

我有這樣的方法來初始化一個緩衝:發行讀/寫一個動態的字節數組註冊表

void CCreateReportDlg::InitAutoAssignStates() 
{ 
    int iNumColumns = m_Grid.GetColumnCount(); 

    ASSERT(m_pbyAutoAssignStates == NULL); 
    if (m_pbyAutoAssignStates == NULL) 
    { 
     m_pbyAutoAssignStates = new BYTE[iNumColumns]; 
     if (m_pbyAutoAssignStates != NULL) 
     { 
      // This sets them all to AUTO_ASSIGN_INCLUDE 
      ZeroMemory(m_pbyAutoAssignStates, iNumColumns * sizeof(BYTE)); 

      // DATE is never used for auto assign 
      m_pbyAutoAssignStates[COLUMN_DATE] = AUTO_ASSIGN_NOT_USED; 
     } 
    } 
} 

到目前爲止,一切都很好。這個緩衝區被傳入一個對話框類。

// Receives pointer to a BYTE* array. 
//  This is owned by the parent. 
void CAutoAssignSettingsDlg::SetAutoAssignStates(BYTE *pbyAutoAssignStates) 
{ 
    m_pbyAutoAssignStates = pbyAutoAssignStates; 
} 

那裏沒問題。然後我在對話框中有一個檢查列表,該列表映射到上述緩衝區中的每個狀態。

在彈出的對話框即將關閉它修改緩衝區:

void CAutoAssignSettingsDlg::UpdateAutoAssignStates() 
{ 
    LVITEM sItem; 
    int  iAssign, iNumAssign; 

    if (m_pbyAutoAssignStates != NULL) 
    { 
     sItem.mask = LVIF_IMAGE|LVIF_PARAM; 
     sItem.iSubItem = 0; 

     iNumAssign = m_listAssign.GetItemCount(); 
     for (iAssign = 0; iAssign < iNumAssign; iAssign++) 
     { 
      sItem.iItem = iAssign; 
      m_listAssign.GetItem(&sItem); 
      if (sItem.iImage == IMG_CHECKED) 
       m_pbyAutoAssignStates[sItem.lParam] = AUTO_ASSIGN_EXCLUDE; 
      else 
       m_pbyAutoAssignStates[sItem.lParam] = AUTO_ASSIGN_INCLUDE; 
     } 
    } 
} 

這一切工作。但後來我想將它保存到註冊表中。目前我這樣做:

theApp.WriteProfileBinary(strSection, _T("AssignStates"), m_pbyAutoAssignStates, sizeof(m_pbyAutoAssignStates)); 

最後,在父對話框中,我調整了從註冊表讀取設置的代碼。所以,現在的InitAutoAssignStates打電話之前我這樣做:

theApp.GetProfileBinary(strSection,_T("AssignStates"), &ppData, &uSize); 
if (uSize > 0) 
{ 
    m_pbyAutoAssignStates = new BYTE[uSize]; 
    memcpy(m_pbyAutoAssignStates, ppData, uSize); 
} 

// Tidy memory 
if (uSize != 0) 
{ 
    delete[] ppData; 
    ppData = NULL; 
} 

隨後InitAutoAssignStates方法只現在被稱爲如果緩衝區是NULL。所以從理論上講,我會回到我保存的緩衝區中。但它不起作用。在我的複選框中勾選的項目集不匹配。

我在做什麼錯?

回答

0

我發現一個相關的問題,說你不能做我想在不知道元素數目的情況下實現的目標。這讓我感到吃驚,但我不會爭辯。

我調整我的代碼中的元素,以彈出對話框的數傳,然後我就能夠節省這樣的:

theApp.WriteProfileBinary(strSection, _T("AssignStates"), 
     m_pbyAutoAssignStates, 
     sizeof(m_pbyAutoAssignStates[0]) * m_iNumAutoAssignStateValues); 

這正常工作。當我讀取這個緩衝區時,我會在列表中找到匹配的複選框。

+0

'sizeof(<指針類型>)'返回一個指針的大小,以字節爲單位。指針和數組是不同的對象,後者可以隱含地衰減到前者中。由於您決定存儲一個指向數組第一個元素的指針,因此您的代碼無法在稍後檢索數組大小。它丟失了。您需要以這種或那種方式存儲長度。 C++爲此提供了容器類。此外,這個答案是錯誤的。它僅適用於32位版本,64位版本無法使用。 – IInspectable

+0

@IInspectable我在64位電腦上運行64位,我沒有看到錯誤。你能解釋一下嗎? –

+2

對於64位進程,'sizeof(m_pbyAutoAssignStates)'爲8。對於64位進程,「sizeof(BYTE)」爲1。表達式'sizeof(m_pbyAutoAssignStates)* m_iNumAutoAssignStateValues'返回所需字節數的8倍。這意味着你正在向註冊表寫入太多的字節,這不像讀取超出數組末尾那麼多的問題。現在這是未定義的行爲,任何事情都可能發生(包括根據需要工作)。這仍然是錯誤的。正確的字節大小是:'sizeof(m_pbyAutoAssignStates [0])* m_iNumAutoAssignStateValues'。 – IInspectable