Тема: Подскажите средства ObjectARX, работающие с оперативной памятью

Очередной булыжник выплыл.
Проблема такова: Есть в моем объекте блок данных (AcArray), который, естественно, периодически сохраняется (pFiler) сохраняется конечно не указатель, а данные :). Затем воссоздается и т.д.
Создается и уничтожается он стандартными средствами new и delete, + присваивается NULL (а перед этим удаляются все элементы массива) в деструкторе.
Временами работает нормально (в Release версии), но периодически выплывает Exception, мол Access violation.
Может кто сталкивался? Подскажите, замахался...
P.S. Вылетает в дебаге на delete[], который пытается удалить удаленный массив, зарубил накорню ассемблером. Немного лучше стало, но все равно вылетает периодически.
Может есть какие-нить средства ObjectARX, работающие с памятью?

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

Что за тип данных. Для своего класса данных надо еще ре-аллоскатор прописать. Вроде этого:

class t_my_class
{
...
};
typedef AcArray< t_my_class, AcArrayObjectCopyReallocator<t_my_class> > my_class_array_t;

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

> Exhumer
Напрасный труд, это компилятор допишет сам

> Sandrick
1. А почему не создавать экземпляр в стеке?

AcArray<my_class> my_aaray;

2. Проверь код записи\чтения масива.
При записи сначал пищем количество элементов, а потом уже все элементы
При чтении сначала надо прочитать количество. А уже потом читаем элементы - ровно столько сколько записали.

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

Я переписал немного систему, теперича вообче бред выходит... массив  задается у меня такими параметрами: AcArray <void*> myArray. Далее я ему даю (*myArray)[0] = malloc (t_size). Все вроде нормально. Но, когда я пытаюсь высвободить массив free((*myArray)[0]) - вылетает Access violation. Указатель существует, размер (_msize((*myArray)[0])), также выходит нормально.
Уже перепробовал "все"... может чего упустил из виду?
P.S. с конструкцией AcArray <myClass>... я уже пробовал, только у меня не класс а структура, которая содержит массив [4] AcGePoint3d + доп параметры. Компиль пытается высвободить эти точки при помощи delete []... и вылетает...
Заранее благодарен.

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

Проблема еще усугубляется тем, что при клике на grip, вызывается полная реконструкция класса, без вызова (до реконструкции) деструктора...

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

Брр.. страшные вещи расказываеш
Вот как сделал бы это я:

class  CMyEnt : public AcDbEntity
{
public:
    virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* filer) const;
    virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* filer);
    
public:
    struct Data
    {
        enum{PointsCount=4};
        AcGePoint3d pnts[PointsCount];
        int    val1;
        double val2;
    };
protected:
    AcArray<Data>  m_dataArr;
};
//Чтение
Acad::ErrorStatus CMyEnt::dwgInFields(AcDbDwgFiler* pFiler)
{
    assertWriteEnabled();    
    // Call dwgInFields from AcDbEntity
    Acad::ErrorStatus es = AcDbEntity::dwgInFields(pFiler);    
    if(es != Acad::eOk) return es;
    
    // Read version number.
    Adesk::UInt16 version;
    pFiler->readItem(&version);
    if(version > VERSION_MY)    return Acad::eMakeMeProxy;
    Adesk::UInt16 size;
    pFiler->readItem(&size);
    m_dataArr.setLogicalLength(size);
    for(int i=0; i< size; ++i){
        for(int j=0; j<Data::PointsCount; ++j)    pFiler->readItem(&m_dataArr[i].pnts[j]);
        pFiler->readItem(&m_dataArr[i].val1);
        pFiler->readItem(&m_dataArr[i].val2);
    }
    return pFiler->filerStatus();
}
Acad::ErrorStatus CMyEnt::dwgOutFields(AcDbDwgFiler* pFiler) const
{
    assertReadEnabled();
    // Call dwgOutFields from AcDbEntity
    Acad::ErrorStatus es = AcDbEntity::dwgOutFields(pFiler);
    if(es != Acad::eOk) return es;
    
    // Write version number.
    pFiler->writeItem((Adesk::UInt16) VERSION_MY);
    Adesk::UInt16 size = m_dataArr.length();
    for(int i=0; i< size; ++i){
        for(int j=0; j<Data::PointsCount; ++j)    pFiler->writeItem(m_dataArr[i].pnts[j]);
        pFiler->writeItem(m_dataArr[i].val1);
        pFiler->writeItem(m_dataArr[i].val2);
    }    
    
    return pFiler->filerStatus();
}//dwgOutFields

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

> Sandrick
Ты бы привёл небольшой кусочек кода, который вызывает проблемы. А то такое чувство, что у тебя там какой-то бред написан...

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

Код приводить, тут конфы не хватит, уже столько понаписано всего (и бреда тоже :) ).
дык, тут-то и проблема, что у меня массив полностью на указателях... и массив задается как AcArray <void*> * myArray (оБшибся вверху).
А Filer у меня не может читать и писать так вот просто pFiler->writeBytes((*myArray)[i],size_t);
А класс при воссоздании создает еще дополнительный массив... который, судя по всему теряется где-то. После клика на grip'e происходят вообще совершенно необъяснимые вещи...

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

> Sandrick
Ты туда пишешь указатели, потом их считываешь и рассчитываешь, что они каждый раз будут указывать туда, куда нужно? wink Наивняк!

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

> Александр Ривилис
Нет, никакой наивности. Пишу давно. Я пишу в файлер НЕ УКАЗАТЕЛИ НЕ АДРЕСА УКАЗАТЕЛЕЙ. Я считываю сначала файлером данные из массива, уничтожаю массив под чистую, затем при воссоздании класса создаю новый массив и загоняю уже в него данные, считанные файлером...
Где вы, сударь, увидели наивность?

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

> Sandrick
Без описания структуры массива и методов dwgIn/dwgOut помочь тебе врядли возможно.

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

ROMA

Напрасный труд, это компилятор допишет сам

Ничего компилятор не пишет. Надо явно указывать, иначе проблемы с перераспределением памяти гарантированны. Проверено на 2000, 2000i, 2002, 2004.
Sandrick. Думаю, что проблемы твои из-за смешивания C-шного и C++ подхода. Ты работаешь через malloc/free, а AcArray через new/delete. Проблемы вэтом случае не минуемы. Т.е. желательно просто добавлять элементы в массив через append.

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

> Exhumer
т.е. сделать не структуру (struct) а именно класс со своим деструктором, который бы удалялся автоматом вместе с указателем?
Тут именно задача в том, чтобы для ускорения процесса хранить указатели на данные в массиве. А данные файлером сохранять и извлекать, каждый раз воссоздавая массив.
============================================
Структура массива такова: Есть структура данных
struct myStruct
{
     bool flag;
     AcGePoint3d points [4];
} *pmyStruct;
AcArray <pmyStruct> myArray;
int index = myArray.append(NULL);
myArray[index] = (void*)malloc(sizeof myStruct);
memcpy (myArray[index],<DATA>, sizeof myStruct);
................................................
и далее деструктор:
free (myArray[<INDEX>]); - и вот тут мы и грохаемся в Access denied
myArray.removeAt(<INDEX>);

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

> Sandrick
Да, в таких случаях я делаю именно класс. Со своим dwgIn/dwgOut. Для ускорения можно сразу резервировать место под определенное кол-во элементов.

class t_my_class
{
public:
  Acad::ErrorStatus dwgOutFields( AcDbDwgFiler *pFiler ) const;
  Acad::ErrorStatus dwgInFields( AcDbDwgFiler *pFiler );
...
};
typedef AcArray< t_my_class, AcArrayObjectCopyReallocator<t_my_class> > my_class_array_t;
Acad::ErrorStatus t_parent_object::dwgInFields( AcDbDwgFiler *pFiler )
{
...
  Adesk::UInt32 count = 0;
  Acad::ErrorStatus es = pFiler->readUInt32( &count );
  my_class_array_t my_class_array( count ):
  my_class_array.setLogicalLength( count );
  for( Adesk::UInt32 i = 0; i < count; i++ )
  {
    my_class_array[i]->dwgInFields( pFiler );
    ...
  }
...
}

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

> Exhumer
Благодарю, буду пробовать...
Полагаю, тема исчерпана.

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

> Sandrick
Насколько я понял, проблема в:

memcpy (myArray[index],<DATA>, sizeof myStruct);

Ты выполняешь "поверхностное копирование" AcGePoint3d, чего делать не следует (конструктор не выполняется). Вот если бы ты не поленился выполнить (myStruct *)(myArray[index])->points[i] = <DATA>->points[i] (i=0...3), то этой ошибки возможно и небыло.

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

> Exhumer
А что по твоему делает это определение?
(взято из acarray.h, строка 133)

template <class T, [b]class R = AcArrayMemCopyReallocator<T> > [/b]class AcArray
{
public:
    AcArray(int initPhysicalLength = 0, int initGrowLength = 8);
    AcArray(const AcArray<T,R>&);
    ~AcArray();
...
};

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

> ROMA
Почуствуй разницу между AcArrayObjectCopyReallocator и AcArrayMemCopyReallocator

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

> ROMA

> Exhumer
Разница приблизительно такая же, как между memcpy(...) и (myStruct *)(myArray[index])->points[i] = <DATA>->points[i]
Так что Exhumer абсолютно прав. Только для простейших структур можно использовать стандартную форму AcArray<T> без указания реалокатора. Если же в структуре (классе) есть экземпляры классов (не указатели), которые имеют конструкторы - то гарантировано требуется реалокатор с AcArrayObjectCopyReallocator
Кстати, если бы структура у Sandrick'а имела вид:

struct myStruct
{
  bool flag;
  ads_point points [4];
} *pmyStruct;


то все бы у него было в порядке - для нее вполне подходит memcpy(...)
Ну а воспользоваться в нужном месте функциями asPnt3d() и asDblArray() я думаю для него не представляло бы проблем и не сильно сказалось на производительности.

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

> Exhumer
Извиняюсь, сначала даже не посмотрел что реализовано 2 Reallocator-а.
:(

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

Александр Ривилис пишет:

Кстати, если бы структура у Sandrick'а имела вид:
struct myStruct
{
  bool flag;
  ads_point points [4];
} *pmyStruct;
то все бы у него было в порядке — для нее вполне подходит memcpy

Да, все именно так...
структура:

AcArray <pmyStruct> myArray;

Добавляем объект:

myArray[index] = (pmyStruct) malloc (sizeof myStruct);
memcpy (myArray[index],&DATA, sizeof DATA);

И вот деструктор:

free(myArray[index]); 

<- Вот тут-то мы и шлкпаемся... пробовал и free ((void*)&(myArray[index])). Рано или поздно спотыкается...
.........................

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

Я мучился с AcArray месяц, плюнул и стал использовать стандартный класс vector (и че я сразу им не стал пользоваться). Глюки пропали.

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

Доброго всем здравия!
В тему:
имеет место customentity, заголовочный файл:

#include ...
#define ...
using namespace std;
    ....
class MyEntity : public AcDbEntity
{
public: ...
private:
    ...
    const list<hed::Node*>* nodes_list;
        //список всех узлов!
    ...
}

cpp файл:

void MyEntity::set_up_points()
{
    ...
    const std::list<hed::Node*>* nodes_list = triang.getNodes();
    //список всех узлов!    
    acutPrintf( "nodes %d",nodes_list->size());    
    //печатаем кол-во узлов, все ок!
}
Acad::ErrorStatus
MyEntity::dwgOutFields(AcDbDwgFiler* filer) const
{
  assertReadEnabled();
  Acad::ErrorStatus es;
  if ((es = AcDbEntity::dwgOutFields(filer)) != Acad::eOk) {
    return es;
  }
    ...
    Adesk::UInt32 size = nodes_list->size());
    //в этом месте даёт ошибку?
      ...
    return es;
}

Не совсем понимаю почему?

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

вопрос снят, глаза замылились, не обратил внимания на простую ошбку области видимости!

Re: Подскажите средства ObjectARX, работающие с оперативной памятью

И все равно дант таки ошибку??

#include ...
#define ...
using namespace std;
  ....
class MyEntity : public AcDbEntity
{
public: ...
private:
  ...
  const list<hed::Node*>* nodes_list;
        //список всех узлов!
  ...
}

cpp файл:

void MyEntity::set_up_points()
{
  ...
   nodes_list = triang.getNodes();
  //список всех узлов!
   std::list<hed::Node*>::const_iterator nit;
    for (nit = nodes_list->begin(); nit != nodes_list->end(); nit++) {
        acutPrintf( "x- %f",(*nit)->x());
        acutPrintf( "y- %f",(*nit)->y());
        acutPrintf( "z- %f\n",(*nit)->z());
    }
  //печатаем кол-во узлов, все ок!
}
Acad::ErrorStatus
MyEntity::dwgOutFields(AcDbDwgFiler* filer) const
{
  assertReadEnabled();
  Acad::ErrorStatus es;
  if ((es = AcDbEntity::dwgOutFields(filer)) != Acad::eOk) {
    return es;
  }
  ...
   Adesk::UInt32 size = nodes_list->size());
   std::list<hed::Node*>::const_iterator nit;
    for (nit = nodes_list->begin(); nit != nodes_list->end(); nit++) {
        acutPrintf( "x- %f",(*nit)->x());
        acutPrintf( "y- %f",(*nit)->y());
        acutPrintf( "z- %f\n",(*nit)->z());
    }
  //в этом месте даёт ошибку?
    ...
  return es;
}