【问题标题】:Got segfault accessing array of pointers to struct when using pointers instead of references使用指针而不是引用时访问指向结构的指针数组时出现段错误
【发布时间】:2012-10-04 11:59:46
【问题描述】:

下面的函数接受一个指向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&amp; 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" );
        }
    }
}

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

【问题讨论】:

标签: c++ c arrays pointers


【解决方案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(指向参数的指针),函数接收指向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 将成为pParams 之后的指针ii,但这不是指向API_AddParType 的指针数组的第一个元素,其大小大于1,因此访问@ 987654347@ 对于ii &gt; 0 来说是未定义的行为,并且由于在pParams 后面不太可能恰好有指向API_AddParType 的有效指针,因此对pParam-&gt;name 的访问分别是。 pParam-&gt;value.real 可能会导致段错误。

ppParams[ii] 出现分段错误,(*ppParams)[ii] 没有出现分段错误这一事实强烈暗示这种情况实际上是第二个,而不是第一个。

【讨论】:

  • 非常感谢!那是第二种情况。完全按照您的建议!
【解决方案2】:

尝试将API_AddParType* pParam = ppParams[ii]; 更改为API_AddParType* pParam = *ppParams; 并像这样pParam[ii].name 访问pParam-&gt;name

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

【讨论】:

    【解决方案3】:

    换行试试

    API_AddParType* pParam = ppParams[ii];
    

    API_AddParType* pParam = (*ppParams) + ii;
    

    【讨论】:

      【解决方案4】:

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

      数组的ii:th 元素在指针情况和其他情况下都是(*ppParams)[ii]
      你正在寻找它的地址,它是

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

      API_AddParType* pParam = (*ppParams) + ii;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-09-20
        • 1970-01-01
        • 2016-09-09
        • 2015-09-10
        • 1970-01-01
        • 1970-01-01
        • 2017-07-18
        相关资源
        最近更新 更多