在使用指针而不是引用时,获得了segfault访问struct的指针数组

时间:2012-10-04 11:59:47

标签: c++ c arrays pointers

下面的函数获取指向API_AddParType结构的指针数组的指针,并列出每个数组元素的一些字段。当使用(*ppParams)[ii]访问每个元素时,一切都像预期的那样:

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" );
        }
    }
}

有分段错误。怎么会这样?为什么它在通过指针访问数据时失败而引用工作没有任何问题?

4 个答案:

答案 0 :(得分:1)

尝试将API_AddParType* pParam = ppParams[ii];更改为API_AddParType* pParam = *ppParams;并访问pParam->name,例如pParam[ii].name

访问(*ppParams)[ii]您正在操纵单个API_AddParType,但访问pParam[ii]您正在操纵API_AddParType数组。

答案 1 :(得分:1)

尝试更改行

API_AddParType* pParam = ppParams[ii];

API_AddParType* pParam = (*ppParams) + ii;

答案 2 :(得分:1)

在最后一种情况下,您将ppParams视为指针数组,而不是指向数组的指针。

数组中的ii:th元素在指针盒中以及其他情况下为(*ppParams)[ii]
你正在寻找它的地址,

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

API_AddParType* pParam = (*ppParams) + ii;

答案 3 :(得分:1)

  

下面的函数指向指向API_AddParType结构

的指针数组
void ParamsListWrapper::ListParams2(API_AddParType** ppParams)

函数的参数是一个指向指针的指针 - API_AddParType,它可以是指向API_AddParType指针数组的第一个元素的指针,

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

或者它可以是一个指针(指向API_AddParType数组的第一个元素的指针),

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

我将匿名内存位置ppParams命名为pParams(指向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,...,看起来不错。

但在第二种情况下,pParam将成为ii之后的指针pParams单位,但这不是指向API_AddParType的指针数组的第一个元素。大小大于1,因此访问ppParams[ii]ii > 0的未定义行为,并且因为API_AddParType后面的pParams不太可能存在有效指针,因此访问pParam->namepParam->value.real resp。 ppParams[ii]可能导致段错误。

您使用(*ppParams)[ii]而非{{1}}的分段错误强烈暗示情况实际上是第二个,而不是第一个。