2012-10-04 52 views
0

下面的函數將指針指向一個指向API_AddParType結構體的指針數組,並列出每個數組元素的一些字段。當使用指針而不是引用時,得到segfault訪問數組的指針

void ParamsListWrapper::ListParams2(API_AddParType** ppParams) 
{ 
    unsigned long ii, nParams; 
    nParams = BMGetHandleSize((GSHandle)ppParams)/sizeof(API_AddParType); 

    // list params 
    for (ii = 0; ii < nParams; ii++) { 
     WriteReport("Param name = \"%s\", double = %f", (*ppParams)[ii].name, (*ppParams)[ii].value.real); 
    } 
} 

好吧,讓我們使用類似API_AddParType& param一些參考變量:

void ParamsListWrapper::ListParams1(API_AddParType** ppParams) 
{ 
    unsigned long ii, nParams; 
    nParams = BMGetHandleSize((GSHandle)ppParams)/sizeof(API_AddParType); 

    // list params 
    for (ii = 0; ii < nParams; ii++) { 
     API_AddParType& param = (*ppParams)[ii]; 
     WriteReport("Param name = \"%s\", double = %f", param.name, param.value.real); 
    } 
} 

現在試圖與指針相同的代碼來API_AddParType

void ParamsListWrapper::ListParams3(API_AddParType** ppParams) 
{ 
    unsigned long ii, nParams; 
    nParams = BMGetHandleSize((GSHandle)ppParams)/sizeof(API_AddParType); 

    // list params 
    for (ii = 0; ii < nParams; ii++) { 
     API_AddParType* pParam = ppParams[ii]; 
     if (pParam != NULL) { 
      WriteReport("Param name = \"%s\", double = %f", pParam->name, pParam->value.real); 
     } else { 
      WriteReport("Param is NULL"); 
     } 
    } 
} 
訪問每一個元素時 (*ppParams)[ii]一切正常,就像預期

出現分段錯誤。怎麼會這樣?通過指針訪問數據時爲什麼失敗,而引用正常工作?

+0

您是否嘗試啓用所有警告和調試信息(例如Linux上的'g ++ -Wall -g')並使用http://valgrind.org/和'gdb'調試器? –

+0

哎呀!我正在爲此項目使用MSVC 2003。 – ezpresso

+0

您可能會考慮http://www-01.ibm.com/software/awdtools/purify/ –

回答

1

下面的函數將一個指向指針數組來API_AddParType結構

void ParamsListWrapper::ListParams2(API_AddParType** ppParams) 

該函數的參數是一個指針指向poi NTER-TO- API_AddParType,這可能是一個指針,指向指針數組以API_AddParType的第一個元素,

ppParams 
    | 
    v 
pParam0|pParam1|pParam2|... 
    |  |  | ... 
    v  v  v 
    xyz  abc  mno ... 

,或者它可以是指向(一個指針的API_AddParType數組的第一元素) ,

ppParams 
    | 
    v 
pParams 
    | 
    v 
param0|param1|param2|... 

,我命名爲匿名內存位置ppParamspParams(指針PARAMS),原因函數接收一個指向pParams而不是pParams本身可能指針pParams本身可能會被功能改變。

現在,在第一種情況下,(*ppParams)[ii] = pParam0[ii] = the object ii units after the start of xyz,所以你從來不看什麼pParam1pParam2等點(除非這些指針被設置爲它的第一個元素pParam1指向數組內點)。

在第二種情況下,(*ppParams)[ii] = pParams[ii] = the object ii units after the start of param0,你看看排列整齊排列的所有paramN。看起來不錯。

隨着

API_AddParType* pParam = ppParams[ii] 
在第一種情況下

,你想看看xyzabcmno,...順序,看起來不錯。

但是在第二種情況下,pParamii單元pParams後成爲指針,但這不是指針數組的大小大於一的API_AddParType的第一要素,所以訪問ppParams[ii]ii > 0未定義的行爲,和因爲不太可能僅僅在pParams之後有API_AddParType的有效指針,所以對pParam->name的訪問分別是。 pParam->value.real可能會導致段錯誤。

事實上,您得到了ppParams[ii]的分段錯誤,但不是(*ppParams)[ii]強烈暗示這種情況實際上是第二種,而不是第一種。

+0

非常感謝!這是第二種情況。完全按照你的建議! – ezpresso

1

嘗試更改API_AddParType* pParam = ppParams[ii];API_AddParType* pParam = *ppParams;並訪問pParam->name像這樣pParam[ii].name

通過訪問(*ppParams)[ii]您操縱單個API_AddParType,但訪問pParam[ii]您操縱的是API_AddParType的數組。

1

嘗試改變線

API_AddParType* pParam = ppParams[ii]; 

API_AddParType* pParam = (*ppParams) + ii; 
1

在最後一種情況下,你在治療ppParams爲指針數組,而不是一個指向數組的指針。

ii:該數組的第th個元素在指針的情況下以及在其他情況下是(*ppParams)[ii]
你在尋找它的地址,這是

API_AddParType* pParam = &(*ppParams)[ii]; 

API_AddParType* pParam = (*ppParams) + ii;