Перейти к содержанию
    

Указатели на объекты С++ IAR EWAVR

Столкнулся с непонятной вещью. Имеется некий класс TBase

 

в хидере



class TBase
{
public: TBase( UCHAR par1, UCHAR par2) // конструктор с двумя параметрами

// Далее методы, данный и т.д.
.........
.........
};

 

В file.cpp реализация.

 

В прилложении создаются объявляются глообальные указатели и создаются два объекта

1 способ, не работает



TBase *Obj[2];

// далее вызов конструкторов

Obj[0] = new TBase( A, B);
Obj[1] = new TBase( C, D);

// Методы вызываются в основной программе
Obj[0] ->Method1();
Obj[1] ->Method1();
..........

 

Поведение программы, как будто создан только один объет Obj[0]

А если сделать вот так



TBase *Obj0;
TBase *Obj1;
// далее вызов конструкторов

Obj0 = new TBase( A, B);
Obj1 = new TBase( C, D);

// Методы вызываются в основной программе

Obj0 ->Method1();
Obj1 ->Method1();

Все работает корректно.

В чем может быть причина или где я не догоняю

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

VladimirYU привели бы весь код, или подробнее объясните, что значит программа ведет себя как будто создан только один объект? Судя по вашему коду, все должно работать корректно.
Изменено пользователем Quasar

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

To SmSp:

В этом случае получится не массив из двух указателей на TBase, а указатель на массив из двух TBase.

 

В коде, который привел VladimirYU, вроде все правильно, возможно, траблы были именно в реализации конструктора TBase или функции-члена Method1(), которые автор не привел.

Изменено пользователем visual_wind

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

To SmSp:

В этом случае получится не массив из двух указателей на TBase, а указатель на массив из двух TBase.

 

В коде, который привел VladimirYU, вроде все правильно, возможно, траблы были именно в реализации конструктора TBase или функции-члена Method1(), которые автор не привел.

К сожалению реализация как конструкторов, так и методов скрыта и доступна только в виде библиотек .r90

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Зачем в АВР динамически выделяемые объекты? И вообще, кто у вас там память выделяет/распределяет? Размер кучи достаточен?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

To VladimirYU:

 

Так а стало понятно, что не работает в варианте с массивом, или, поскольку все заработало в варианте без массива, то все ок и дальше нет смысла копаться?

 

Если есть необходимость разбираться дальше:

 

Из-под ссей можно еще просмотреть корректность работы оператора new (в разных ли местах выделяется память под рассматриваемые два экземпляра и с правильными ли параметрами вызываются конструкторы TBase). Возможно, кстати, что класс TBase перегружает operator new и там какой-то глюканат из-за оптимизации, например. Если есть полное описание класса TBase, можно еще после конструирования попытаться проверить корректность инициализации переменных класса TBase конструктором.

 

Если полного описания класса нет, а только интерфейс, шанс еще есть в анализе дизассемблерного кода.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

To SmSp:

В этом случае получится не массив из двух указателей на TBase, а указатель на массив из двух TBase.

 

В коде, который привел VladimirYU, вроде все правильно, возможно, траблы были именно в реализации конструктора TBase или функции-члена Method1(), которые автор не привел.

Путаешь.

TBase (*Obj)[2]; // обявлен массив из двух указателей на Obj

TBase *(Obj[2]); // обявлен указатель на массив из двух Obj

Не помню, у чего тут больше приоритет, поэтому предположил автору убедиться что объявлил он то что хотел.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

To SmSp:

 

Могу и ошибаться. Чтоб лишний раз не спорить, предлагаю посмотреть Кернигана/Ричи, стр.111, последний абзац.

 

Что касается приоритетов, то поскольку приоритет оператора[] выше приоритета оператора*, то использовать скобки в варианте TBase *(Obj[2]) смысла нет, а в варианте TBase (*Obj)[2] скобки как раз меняют приоритеты, то есть, сначала operator*, затем operator[], затем TBase. Итого, Obj есть указатель (operator*) на массив (operator[]) из двух ([2]) TBase.

Изменено пользователем visual_wind

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Дык, ёлки!

 

Всё верно, точнее у VladimirYU ошибка. Он обявил указатель на массив из двух TBase:

 

TBase *Obj[2];

 

Не забываем что массив в си есть указатель на первый элемент массива, имеет тип *TBase. Так, Obj есть указатель на указатель на первый элемент массива из TBase.

 

Первой строкой разименовал указатель (Obj[0] == *(Obj+0)), записал туда указатель на свежесозданный экземпляр TBase. Имеем указатель на указатель на массив, первый элемент которого проинициализирован:

 

Obj[0] = new TBase( A, B);

 

Вторая строка записывает указатель на свжесозданный экземпляр TBase по адресу Obj + 1:

 

Obj[1] = new TBase( C, D);

 

А это ошибка, т.к. используем указатель как массив, в итоге обращаясь к незанятой ячейки памяти.

 

Всё равно что объявить

 

TBase* pointer1;

 

и затем обратиться

 

*(pointer1 + 1) = bla bla;

 

Отсюда и неправильное поведение программы. Надо внимательнее, это же си.

Изменено пользователем SmSp

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

To SmSp: Мое видение проблемы:

 

У VladimirYU в том коде, что он привел, ошибок нет. Он НЕ объявлял указатель на массив из двух TBase, для чего надо использовать объявление TBase (*Obj)[2]. Он объявил массив из двух указателей на TBase, для чего и использовал правильное объявление TBase *Obj[2]. Это разные вещи, согласитесь.

 

Чтобы не пускаться дальше в дискуссию об указателях на указатели и о том, что обозначает имя массива, я в Visual C++ Express Edition 2008 собрал простенький пример.

 

class TBase
{
private:
    char char1;
    char char2;
public:
    TBase( char c1, char c2 ): char1( c1 ), char2( c2 ) {}
    void Method1(){ cout << char1 << char2; }
    virtual ~TBase(){}
};

TBase* tb[2] = { NULL, NULL };

int _tmain(int argc, _TCHAR* argv[])
{
    tb[0] = new TBase( '1', '2' );
    tb[1] = new TBase( '3', '4' );

    tb[0]->Method1();
    tb[1]->Method1();

    delete tb[0];
    delete tb[1];

    return 0;
}

 

У меня этот код работает правильно и печатает "1234". Можете проверить у себя.

 

На мой взляд, проблема у VladimirYU в другом, но пока не понятно в чем.

Изменено пользователем visual_wind

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

visual_wind, ты же сам написал, что приоритет оператора[] выше приоритета оператора*. Значит, VladimirYU объявил указатель на массив.

А тот факт, что приведённый тобой код работает, означает что программа не затирает указатель по адресу tb+1, что в общем случае он может сделать и делает в программе VladimirYU (цитирую: "как будто создан только один объет Obj[0]").

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

То SmSp:

 

По-моему, мы вместо помощи человеку начали разводить флейм и нарываемся на бан. И камень преткновения - что же на самом деле объявлено - указатель на массив из двух TBase или массив из двух указателей на TBase. Обратимся непосредственно к K&R:

 

"Таким образом, если массив daytab передается некоторой функции f, то эту функцию можно было бы определить следующим образом

f( char daytab[2][13] ){...}

Вместо этого можно записать

f( char daytab[][13] ){...}

поскольку число строк здесь не имеет значения, или

f( char (*daytab)[13] ){...}

последняя запись декларирует, что параметр есть указатель на массив из 13 значений типа char. Скобки здесь необходимы, так как квадратные скобки [] имеют более высокий приоритет, чем *. Без скобок декларация

f( char *daytab[13] ){...}

определяет массив из 13 указателей на char. В более общем случае только первое измерение (соответствующее первому индексу) можно не задавать, все другие специфицировать необходимо" © K&R, стр.111-112, изд.2-е, переработанное,1992.

 

Насколько я понимаю, у VladimirYU все в порядке в том коде, который он привел.

Изменено пользователем visual_wind

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Он обявил указатель на массив из двух TBase:

Ни чего он такого не объявлял.

 

Надо внимательнее, это же си.

Вот именно.

 

Возмите, да под какой-нибудь системой(которая способна ошибку сегментации выдать) соберите код:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(void){
    int i,*arr[10],*arr2[10];
    printf("Part 1\n");
    for (i = 0; i < (sizeof(arr)/sizeof(int*));i++){
        printf ("i = %d\n",i);
        arr[i] = (int*)malloc(sizeof(int));
        *arr[i] = i;
    }
    for (i = 0; i < (sizeof(arr)/sizeof(int*));i++){
        printf ("n = %d\n",*arr[i]);
    }
    printf ("Part 2\n");
    for (i = 0; i < (sizeof(arr2)/sizeof(int*));i++){
        printf ("i = %d\n",i);
        *arr2[i] = i;
    }
    return 0;
}

 

VladimirYU

Проблема где-то не в массиве.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

VladimirYU

Проблема где-то не в массиве.

Я тоже к этому склоняюсь, но дело в том, что объекты в моем случае это физические приборы обращение к которым от "мамы" по SPI шине. Реализация класса, поддерживающего их, скрыта, есть только интерфейс .h и .r90. В общем пока обхожу эту проблему, но в дальнейшем придется разбираться. Всем спасибо за участие, за одно и лишний раз в стандарте покапался.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...