реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Указатели на объекты С++ IAR EWAVR
VladimirYU
сообщение Sep 1 2009, 13:09
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 426
Регистрация: 5-04-07
Из: Санкт-Петербург
Пользователь №: 26 782



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

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

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


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

В прилложении создаются объявляются глообальные указатели и создаются два объекта
1 способ, не работает
Код
[/code]
TBase *Obj[2];

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

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

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


Поведение программы, как будто создан только один объет Obj[0]
А если сделать вот так
Код
[/code]
TBase *Obj0;
TBase *Obj1;
// далее вызов конструкторов

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

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

Obj0 ->Method1();
Obj1 ->Method1();
[code]

Все работает корректно.
В чем может быть причина или где я не догоняю
Go to the top of the page
 
+Quote Post
Quasar
сообщение Sep 6 2009, 19:42
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 257
Регистрация: 2-12-06
Из: Default City
Пользователь №: 23 021



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

Сообщение отредактировал Quasar - Sep 6 2009, 19:46
Go to the top of the page
 
+Quote Post
SmSp
сообщение Sep 17 2009, 06:58
Сообщение #3





Группа: Участник
Сообщений: 11
Регистрация: 26-02-08
Пользователь №: 35 394



А если объявить так?

TBase (*Obj)[2];
Go to the top of the page
 
+Quote Post
visual_wind
сообщение Sep 17 2009, 08:13
Сообщение #4





Группа: Участник
Сообщений: 8
Регистрация: 29-04-09
Из: Харьков
Пользователь №: 48 442



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

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

Сообщение отредактировал visual_wind - Sep 17 2009, 08:14
Go to the top of the page
 
+Quote Post
VladimirYU
сообщение Sep 17 2009, 09:51
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 426
Регистрация: 5-04-07
Из: Санкт-Петербург
Пользователь №: 26 782



Цитата(visual_wind @ Sep 17 2009, 12:13) *
To SmSp:
В этом случае получится не массив из двух указателей на TBase, а указатель на массив из двух TBase.

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

К сожалению реализация как конструкторов, так и методов скрыта и доступна только в виде библиотек .r90
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Sep 18 2009, 06:27
Сообщение #6


тут может быть ваша реклама
*****

Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280



Зачем в АВР динамически выделяемые объекты? И вообще, кто у вас там память выделяет/распределяет? Размер кучи достаточен?
Go to the top of the page
 
+Quote Post
visual_wind
сообщение Sep 18 2009, 06:33
Сообщение #7





Группа: Участник
Сообщений: 8
Регистрация: 29-04-09
Из: Харьков
Пользователь №: 48 442



To VladimirYU:

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

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

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

Если полного описания класса нет, а только интерфейс, шанс еще есть в анализе дизассемблерного кода.
Go to the top of the page
 
+Quote Post
SmSp
сообщение Sep 18 2009, 06:48
Сообщение #8





Группа: Участник
Сообщений: 11
Регистрация: 26-02-08
Пользователь №: 35 394



Цитата(visual_wind @ Sep 17 2009, 12:13) *
To SmSp:
В этом случае получится не массив из двух указателей на TBase, а указатель на массив из двух TBase.

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

Путаешь.
TBase (*Obj)[2]; // обявлен массив из двух указателей на Obj
TBase *(Obj[2]); // обявлен указатель на массив из двух Obj
Не помню, у чего тут больше приоритет, поэтому предположил автору убедиться что объявлил он то что хотел.
Go to the top of the page
 
+Quote Post
visual_wind
сообщение Sep 18 2009, 08:57
Сообщение #9





Группа: Участник
Сообщений: 8
Регистрация: 29-04-09
Из: Харьков
Пользователь №: 48 442



To SmSp:

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

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

Сообщение отредактировал visual_wind - Sep 18 2009, 08:58
Go to the top of the page
 
+Quote Post
SmSp
сообщение Sep 18 2009, 11:43
Сообщение #10





Группа: Участник
Сообщений: 11
Регистрация: 26-02-08
Пользователь №: 35 394



Дык, ёлки!

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

TBase *Obj[2];

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

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

Obj[0] = new TBase( A, cool.gif;

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

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

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

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

TBase* pointer1;

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

*(pointer1 + 1) = bla bla;

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

Сообщение отредактировал SmSp - Sep 18 2009, 11:46
Go to the top of the page
 
+Quote Post
visual_wind
сообщение Sep 18 2009, 13:22
Сообщение #11





Группа: Участник
Сообщений: 8
Регистрация: 29-04-09
Из: Харьков
Пользователь №: 48 442



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 - Sep 18 2009, 13:42
Go to the top of the page
 
+Quote Post
SmSp
сообщение Sep 18 2009, 13:41
Сообщение #12





Группа: Участник
Сообщений: 11
Регистрация: 26-02-08
Пользователь №: 35 394



visual_wind, ты же сам написал, что приоритет оператора[] выше приоритета оператора*. Значит, VladimirYU объявил указатель на массив.
А тот факт, что приведённый тобой код работает, означает что программа не затирает указатель по адресу tb+1, что в общем случае он может сделать и делает в программе VladimirYU (цитирую: "как будто создан только один объет Obj[0]").
Go to the top of the page
 
+Quote Post
visual_wind
сообщение Sep 18 2009, 14:01
Сообщение #13





Группа: Участник
Сообщений: 8
Регистрация: 29-04-09
Из: Харьков
Пользователь №: 48 442



То 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 - Sep 18 2009, 14:03
Go to the top of the page
 
+Quote Post
Quasar
сообщение Sep 20 2009, 22:07
Сообщение #14


Местный
***

Группа: Свой
Сообщений: 257
Регистрация: 2-12-06
Из: Default City
Пользователь №: 23 021



Цитата(SmSp @ Sep 18 2009, 15:43) *
Он обявил указатель на массив из двух TBase:

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

Цитата('SmSp' date='Sep 18 2009 @ 15:43' post='651718')
Надо внимательнее, это же си.

Вот именно.

Возмите, да под какой-нибудь системой(которая способна ошибку сегментации выдать) соберите код:
Код
#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
Проблема где-то не в массиве.
Go to the top of the page
 
+Quote Post
VladimirYU
сообщение Sep 21 2009, 06:02
Сообщение #15


Местный
***

Группа: Свой
Сообщений: 426
Регистрация: 5-04-07
Из: Санкт-Петербург
Пользователь №: 26 782



Цитата(Quasar @ Sep 21 2009, 02:07) *
VladimirYU
Проблема где-то не в массиве.

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

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 16:12
Рейтинг@Mail.ru


Страница сгенерированна за 0.01483 секунд с 7
ELECTRONIX ©2004-2016