Арифметика и наследование указателей приводят к неопределенному поведению - PullRequest
0 голосов
/ 01 марта 2019

При запуске моей программы она завершается при выполнении cout<<Core32->name() во второй раз.После изучения проблемы я узнал, что арифметика указателей в этом случае приводит к проблемам.Также я смог решить проблему, заменив Core32++; на Core32+04; (не знаю, почему это работает).Тем не менее, мой вопрос заключается в том, почему я смог назвать Метод Core32->procfun(), а не Core32->name().Я посмотрел нарезку объектов, но это, похоже, не решило мою проблему.

РЕДАКТИРОВАТЬ: хотел знать, почему он может вызывать только procfun (), но не name ().Это пример из старого экзамена

#include <iostream>
#include<string>

using namespace std;

class Prozessor{
public:
    virtual string name()=0;
};

class ARM : public Prozessor{
public:
    virtual string name(){return "VAR";};
    virtual int procbitw()=0;
    string procfun(){return "VFP";};
};

class ARMv7:public ARM{
public:
    int procbitw(){return 32;};
    string procfun(){return "VFP";};
};

class ARMv8:public ARM{
public:
    int procbitw(){return 64;};
    string procfun(){return "VFP, NEON";};
};

int main()
{
    const unsigned int n_cores=4;

    ARM *HetQuadCore[n_cores]={new ARMv7, new ARMv7, new ARMv8, new ARMv8};
    ARMv7* Core32=(ARMv7*)HetQuadCore[0];
    for(int i =0;i<n_cores;i++)
    {
        cout<<Core32->procfun()<<endl;
        cout<<Core32->name()<<endl;
        cout<<"Bandwith is "<<HetQuadCore[i]->procbitw()<<endl;
        Core32++;
    }
    return 0;
}

Ответы [ 3 ]

0 голосов
/ 01 марта 2019

вопрос в том, почему я смог вызвать Метод Core32->procfun(), но не Core32->name()

Поскольку поведение не определено.

Оно не определено в обоихслучаев.Одним из возможных вариантов поведения является то, что «Я смог вызвать метод» .Другое возможное поведение - «моя программа завершает работу» .

Также я смог решить проблему, заменив Core32 ++;с Core32 + 04

Одно возможное поведение может выглядеть как «я смог решить проблему» , но только то, что это может показаться, не означает, что неопределенное поведениебыла исправлена.

Проблема в том, что Core32 не является указателем на элемент массива, поэтому его приращение не приводит к допустимому объекту.Вы можете сделать что-то вроде этого:

for(int i =0;i<n_cores;i++)
{
    if (auto ptr7 = dynamic_cast<ARMv7*>(HetQuadCore[i]))
        cout<<ptr7->procfun()<<endl;
    else if (auto ptr8 = dynamic_cast<ARMv8*>(HetQuadCore[i]))
        cout<<ptr8->procfun()<<endl;
    cout<<HetQuadCore[i]->name()<<endl;
    cout<<"Bandwith is "<<HetQuadCore[i]->procbitw()<<endl;
    Core32++;
}

Однако, может быть, лучше вместо этого сделать procfun виртуальным.

0 голосов
/ 01 марта 2019

Вы увеличиваете не ту вещь.

У вас есть массив указателей, верно?И у вас также есть указатель на указатель в этом массиве .

Вы увеличиваете один из указателей объекта, а не указатель массива.

Array      Hypothetical     Objects              Your pointer
          "array pointer"  (scattered)             "Core32"
                                                       ┃
╔══════╗ «━━━━ aPtr            ╔═══════╗               ┃
║ ptr1 ║━━━━━━━━━━━━━━━━━━━━━━»║ ARMv7 ║«━━━━━━━━━━━━━━┛
╠══════╣   ↓  ++aPtr           ╚═══════╝
║ ptr2 ║━━━━━━━━━━━━━━━━━━━━━━━━┓                  ╔═══════╗
╠══════╣   ↓  ++aPtr            ┃  ╔═══════╗  ┏━━━»║ ARMv8 ║
║ ptr3 ║━━━━━━━━━━━━━━━━━━━━━━┓ ┗━»║ ARMv7 ║  ┃    ╚═══════╝
╠══════╣   ↓  ++aPtr          ┃    ╚═══════╝  ┃
║ ptr4 ║━━━━━━━━━━━━━━━━━━━━━┓┗━━━━━━━━━━━━━━━┛  ╔═══════╗
╠══════╣   ↓  ++aPtr         ┗━━━━━━━━━━━━━━━━━━»║ ARMv8 ║
║   …  ║                                         ╚═══════╝
╙┄┄┄┄┄┄╜

Потому чтоэти объекты [потенциально] разбросаны, увеличение Core32 просто дает вам вздор.Это никогда не может быть гарантировано работать.Он будет работать только тогда, когда вызовы new дали вам динамически размещенные объекты, смежные в памяти.

Вы должны просто использовать i, чтобы выполнить итерацию массива, как вы уже делаете, или взятьуказатель aPtr, который перебирает элементы массива, затем разыменовывается во второй раз, чтобы получить объект, на который указывает элемент .

0 голосов
/ 01 марта 2019

Вы можете вызвать Core32->procfun, потому что это не виртуальная функция (поэтому нет необходимости обращаться к vtable) и не использовать никакие внутренние данные.
Возможно, при любом доступе к внутренним данным произойдет сбой, так как this параметр недействителен.

...