Переключение на Главную Страницу Страницы: [1]  ОтправитьПечать
Горячая тема (более 10 ответов) Очередной глобальный баг 1С, мешающий использованию ООП (и не только) (число прочтений - 4934 )
dfuy
Junior Member
**
Отсутствует



Сообщений: 41
Зарегистрирован: 18. Марта 2013
Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
25. Апреля 2017 :: 08:27
Печать  
Обнаружена крайне неприятная особенность механизма возврата значения из функций, которая в сочетании с другой глобальной особенностью приводит к непредсказуемому поведению программы, использующей функции, которые возвращают объекты.

Начнём по порядку.
Значения из функций возвращаются следующим образом: в CExecutedModule есть значение типа CValue, в которое кладётся возвращаемое оператором "Возврат" значение (см. переменную m_FuncRetVal ниже в структурах). Если говорить о внешнем вызове функций из модулей методом CBLModule7::CallAsFunc, то после отработки кода функции этот метод извлекает значение из CexecutedModule::m_FuncRetVal, помещает его по месту назначения параметра CValue &retValue, после чего пытается почистить m_FuncRetVal.

Именно ПЫТАЕТСЯ, потому как получается не очень успешно. Выполняет он это по всем признакам с помощью метода CValue::Reset. И вот тут мы подходим ко второй глобальной особенности, которая мне уже и раньше немало крови попортила. Там (в CValue::Reset и в соседних типа SetTypeByCode) какие-то очень умные*анские программисты решили не вызывать UnlinkContext(). Ну а зачем, в самом деле, пусть остаётся! В итоге, если в переменной был объект (CBLContext в смысле), то после такой "чистки" снаружи она будет выглядеть как пустая, однако ссылка на CBLContext останется со всеми примочками (CBLContext::m_RefCount, CBLContext::m_Array со ссылкой на CexecutedModule::m_FuncRetVal).

(Хотя на самом деле ещё более умные люди до них решили возвращать значение из функции посредством переменной вместо помещения его в стек калькулятора, в случае чего данной проблемы не существовало бы вообще, но не будем о грустном...)

В итоге при возврате из функций объектов ссылка на эти объекты зависает в глубинах модуля, в результате чего любая более-менее нетривиальная программа с использованием ООП (в особенности, конечно, деструкторов) начинает вести себя совершенно непредсказуемо. Объекты удаляются не в том порядке, в котором ожидалось, причём в совершенно случайном месте программы, которое к ним вообще не имеет никакого отношения. А при определённом стечении обстоятельств программа способная вообще полностью выпасть в осадок.
  
Наверх
 
IP записан
 
dfuy
Junior Member
**
Отсутствует



Сообщений: 41
Зарегистрирован: 18. Марта 2013
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #1 - 25. Апреля 2017 :: 08:28
Печать  
Для себя решение я, конечно, придумал. Опишу в двух словах.
1. Метод типа CValue::Reset, только с вызовом UnlinkContext(). Использую для очистки значений его везде.
2. Вызов CBLModule7::CallAsFunc выполняю примерно так:
Код
Выбрать все
 	int ExCallAsFunc(int Index,CValue &Value,PValue *Params,int ParamCount)
	{
		int Result;
		CValue &FuncRetVal=pIntInfo->pExecutedModule->m_FuncRetVal;
		if (&Value==&FuncRetVal)
		{
			CValue Temp; // Только через временную переменную, потому что при выходе из CallAsFunc почистится m_FuncRetVal и в Value будет пустота
			Result=CBLModule7::CallAsFunc(Index,Temp,ParamCount,Params);
			Value=Temp;
		}
		else
		{
			Result=CBLModule7::CallAsFunc(Index,Value,ParamCount,Params);
			FuncRetVal.UnlinkContext(); // В CValue::Reset() нет UnlinkContext(), поэтому при возврате объекта ссылка на него зависнет в m_FuncRetVal
		}
		return Result;
	} 


Тут добавлена обработка ещё одного варианта, который возникает при вызове собственных методов модуля, но не напрямую, а через контекст. В итоге вложенные вызовы CBLModule7::CallAsFunc пишут возвращаемое значение в одну и ту же переменную, из-за чего образуется бардак.

Как глобально разобраться с проблемой UnlinkContext() – хз. Только трапов наставить на соответствующие методы CValue. Но они могут и инлайниться, так что без толку. А ведь эта проблема будет возникать везде, и корректная работа будет гарантирована только при использовании собственных модулей (и то только определенным образом).

В общем, это всё, что пока хотел сказать.
  
Наверх
 
IP записан
 
dfuy
Junior Member
**
Отсутствует



Сообщений: 41
Зарегистрирован: 18. Марта 2013
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #2 - 25. Апреля 2017 :: 08:31
Печать  
Выжимка из незаменимого IDA-файлика со структурами.
См. переменную m_FuncRetVal в CExecutedModule.
Код
Выбрать все
class CExecutedModuleObject
{
	CPtrArray Arr1;
	CPtrArray Arr2;
	CPtrArray Arr3;
};

struct CExecuteStack
{
	DWORD dwData[18];
};

class CExecutedModule
{
	CBLModule *m_pModule;
	CCompiledModule *m_pCompiledModule;
	void *m_pObject1;
	CExecuteStack *m_pStack; // массив - внутренний стек
	DWORD val_5;
	int m_StackSize; // количество переменных в стеке
	CValue *pValArr1;
	DWORD val_8;
	int m_ValCount1;
	DWORD val_10;
	DWORD m_OperPos; // Формируется в процессе выполнения EvalExpr
	DWORD m_OperCode;
	CDWordArray m_DWordArray1;
	CDWordArray m_DWordArray2;
	DWORD val_23;
	DWORD val_24;
	DWORD val_25;
	DWORD val_26;
	DWORD val_27;
	DWORD val_28;
	CValue m_FuncRetVal;
	DWORD m_dwLoadedModuleID;
	DWORD val_29;
	DWORD val_30;
	CBLContext *m_pSomeContext;
	CValue m_Value2;
	CString m_Str0;
	CString m_Str1;
	CString m_Str2;
	DWORD val_31;
	DWORD val_32;
	DWORD val_33;
	CValue *m_pValArr2;
	int m_ValCount2;
	DWORD val_34;
	CExecutedModuleObject Object;
	void *m_pObject2;
	DWORD val_35;
	DWORD val_36;
	CValue **m_ppEvalValArr____________________________________________; // Параметр ValArr метода EvalExpr
	DWORD val_37;
	DWORD val_38;
}; 


  
Наверх
 
IP записан
 
dfuy
Junior Member
**
Отсутствует



Сообщений: 41
Зарегистрирован: 18. Марта 2013
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #3 - 29. Апреля 2017 :: 20:45
Печать  
Дефект не подтверждается при родном вызове функций внутри кода (при вызове их из языка 1С). Видимо там всё делается относительно корректно. Недоделка существует именно в методе CBLModule7::CallAsFunc. Именно там не очищается контекст в переменной, в которой хранится возвращаемое функцией значение, и проблема возникает только при использовании вызовов CallAsFunc из собственных модулей (в таких объектах 1С++, например, как ИсполняемыйМодуль, в ООП, в CModuleEventManager видел ещё, ну и т.д.). Приведённое решение с добавлением UnlinkContext после CallAsFunc в этом случае работает, "глобального" решения проблемы вроде как не требуется.
  
Наверх
 
IP записан
 
trad
1c++ power user
1c++ donor
1c++ moderator
Отсутствует



Сообщений: 3046
Местоположение: Киров
Зарегистрирован: 23. Мая 2006
Пол: Мужской
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #4 - 01. Мая 2017 :: 18:23
Печать  
если интересно, гуглинг дает такие ссылки по теме:
http://www.1cpp.ru/forum/YaBB.pl?num=1212645215
http://www.1cpp.ru/forum/YaBB.pl?num=1207661901
  

1&&2&&3
Наверх
 
IP записан
 
dfuy
Junior Member
**
Отсутствует



Сообщений: 41
Зарегистрирован: 18. Марта 2013
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #5 - 02. Мая 2017 :: 19:59
Печать  
Да, тема там именно эта обсуждается (я подозревал, что не первый на такое нарвался, но не представлял как такое гуглить). Однако к результату что-то это ни к какому не привело. Никакого решения в 1С++ я не увидел (а туда я первым делом слазил). То есть там этот баг должен присутствовать по определению. Я не пытался его воспроизвести, ибо соотв. объектами 1С++ не пользуюсь, но теоретически его не может не быть. Поэтому и решил, что будет не лишним обратить на это внимание.
  
Наверх
 
IP записан
 
dfuy
Junior Member
**
Отсутствует



Сообщений: 41
Зарегистрирован: 18. Марта 2013
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #6 - 02. Мая 2017 :: 20:50
Печать  
Кстати, насчёт поста http://www.1cpp.ru/forum/YaBB.pl?num=1212645215/2#2
Тоже сталкивался с таким. При присвоении пустого значения (CValue::type == 0) вызывается CValue::Reset, в котором, как указано выше, нет UnlinkContext и ссылка на объект (если он был в переменной, которой происходит присвоение) останется. При присвоении любого другого значения ссылка на контекст успешно потрётся. Это не баг реализации ПолучитьПустоеЗначение(), а недоделка CValue::Reset, которая и приводит ко всему букету багов.
Веселился с этим глюком, когда пытался почистить статические переменные модуля методом SetStaticVarValue. Прямого доступа к переменной получить никак нельзя, а присвоение пустого значения ссылки на объекты не удаляло. Приходилось пустую строку присваивать. Так вот.
  
Наверх
 
IP записан
 
vladimirmir2012
Senior Member
****
Отсутствует


1C++ rocks!

Сообщений: 426
Зарегистрирован: 18. Мая 2011
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #7 - 03. Мая 2017 :: 13:41
Печать  
.
« Последняя редакция: 13. Сентября 2018 :: 06:27 - vladimirmir2012 »  
Наверх
 
IP записан
 
dfuy
Junior Member
**
Отсутствует



Сообщений: 41
Зарегистрирован: 18. Марта 2013
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #8 - 03. Мая 2017 :: 20:15
Печать  
vladimirmir2012 писал(а) 03. Мая 2017 :: 13:41:
В 1С 7.7 присвоение пустой строки какому-либо объекту инициирует вызов деструктора объекта /для C++ class например производится вызов его destructor/

Речь не о языке 1С, а о внутреннем устройстве класса CValue. Безусловно присвоение переменной, ссылающейся на объект, некоторого (любого) значения должно приводить - только не к вызову деструктора, а к уменьшению счетчика ссылок на объект (а там уж если больше на него никто не ссылается, то и к вызову деструктора). И вот это не верно в частном случае присвоения значения с CValue::type==0 (в терминах языка 1С ПолучитьПустоеЗначение() без параметров). В этом случае вызывается метод CValue::Reset, в котором CValue::type становится равным 0, но очистка ссылки на объект не происходит. И ссылка висит там пока не будет присвоено какое-либо иное значение с CValue::type<>0, либо переменная не выйдет из области видимости текущего кода, в случае чего будет вызван деструктор ~CValue, который ссылку таки почистит. И вот отсутствие очистки ссылки на объект в методе CValue::Reset в операторе присваивания (см. ниже) и приводит ко всем описанным багам.

Дойдут руки - навешаю-таки трап на CValue::Reset CValue::оperator=. Уверен (надеюсь) в местах, о которых идёт речь он не заинлайнен (проверить пока времени не было, боем проверить проще) Точно не заинлайнен. Заменю его на свой метод с UnlinkContext и это разом решит все проблемы. Все затычки можно будет выкинуть.
« Последняя редакция: 04. Мая 2017 :: 18:56 - dfuy »  
Наверх
 
IP записан
 
dfuy
Junior Member
**
Отсутствует



Сообщений: 41
Зарегистрирован: 18. Марта 2013
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #9 - 04. Мая 2017 :: 13:24
Печать  
Вру, конечно (давно дело было, подзабыл немного). При присвоении значения с CValue::type==0 не делается CValue::Reset. Вообще ничего не делается кроме установки типа. Везде UnlinkContext() есть кроме default. Вот так выглядит оператор присваивания значения в 1С:
Код
Выбрать все
.............
    else                                        // int CValue::IsTypeSafe()
    {
      if ( pSource )
        psrcType = &pSource->Type;
      else
        psrcType = 0;
      srcType = psrcType->m_TypeCode;
      this->Type.m_TypeCode = srcType;
      this->Type.m_TypeID = psrcType->m_TypeID;
      this->Type.m_Length = 0;
      this->Type.m_Precision = 0;
      this->Type.m_Flags = 0;
      switch ( srcType )
      {
        case 1u:
          CNumeric::operator=(&this->Number, &pSource->Number);
          CValue::UnlinkContext(this);
          break;
        case 2u:
          CString::operator=(&this->String, &pSource->String);
          CValue::UnlinkContext(this);
          break;
        case 3u:
          this->Date.m_Date = pSource->Date.m_Date;
          CValue::UnlinkContext(this);
          break;
        case 10u:
        case 11u:
        case 12u:
        case 13u:
        case 14u:
        case 15u:
        case 16u:
        case 17u:
        case 100u:
          this->ObjID.m_ObjID = pSource->ObjID.m_ObjID;
          this->ObjID.DBSign.m_Sign = pSource->ObjID.DBSign.m_Sign;
          m_Context = this->m_Context;
          this->m_ValTypeID = pSource->m_ValTypeID;
          if ( m_Context != pSource->m_Context )
          {
            if ( m_Context )
            {
              CBLContext::RemoveFromValues(m_Context, this);
              this->m_Context->vtable->DecrRef(this->m_Context);
            }
            srcContext = pSource->m_Context;
            this->m_Context = srcContext;
            if ( srcContext )
            {
              srcContext->vtable->IncrRef(srcContext);
              CBLContext::AddToValues(this->m_Context, this);
            }
            else if ( this->Type.m_TypeCode == 100 )
            {
              Empty.m_TypeCode = 0;
              Empty.m_Length = 0;
              Empty.m_Precision = 0;
              Empty.m_Flags = 0;
              Empty.m_TypeID = 0;
              v22 = 0;
              CValue::SetType(this, &Empty);
            }
          }
          break;
        default:
          break;
      }
    } 


В CValue::Reset UnlinkContext() как раз есть:
Код
Выбрать все
void __thiscall CValue::Reset(CValue *this)
{
  CString *m_String; // edi@1
  char *pSign; // ecx@1
  int m_length; // esi@4

  m_String = &this->String;
  CString::operator=(&this->String, ZeroString);
  CNumeric::operator=(&this->Number, 0);
  pSign = (char *)&this->ObjID.DBSign;
  this->Date.m_Date = 0;
  this->ObjID.m_ObjID = 0;
  *(_WORD *)pSign = '  ';
  pSign[2] = ' ';
  this->m_ValTypeID = 0;
  CValue::UnlinkContext(this);
  if ( this->vtable->IsTypeSafe(this) )
  {
    if ( this->Type.m_TypeCode == 2 )
    {
      m_length = this->Type.m_Length;
      if ( m_length > 0 )
        Pad(m_String, m_length, 0);
    }
  }
  else
  {
    this->Type.m_TypeCode = 0;
    this->Type.m_TypeID = 0;
    this->Type.m_Length = 0;
    this->Type.m_Precision = 0;
    this->Type.m_Flags = 0;
  }
} 


Видимо очистка m_FuncRetVal в CallAsFunc делается присвоением пустого значения. Щас покопаю...
  
Наверх
 
IP записан
 
dfuy
Junior Member
**
Отсутствует



Сообщений: 41
Зарегистрирован: 18. Марта 2013
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #10 - 04. Мая 2017 :: 13:34
Печать  
В самом языке операцию очистки значения m_FuncRetVal уже видел, она делается через CValue::SetType(). В SetType UnlinkContext есть:
Код
Выбрать все
void __thiscall CValue::SetType(CValue *this, const CType *aType)
{
  CType *pType; // eax@3

  CValue::UnlinkContext(this);
  if ( this->vtable->IsTypeSafe(this) )
  {
    if ( this )
      pType = &this->Type;
    else
      pType = 0;
    *pType = *aType;
    this->m_ValTypeID = 0;
  }
  else
  {
    this->Type.m_TypeCode = aType->m_TypeCode;
    this->Type.m_TypeID = aType->m_TypeID;
    this->Type.m_Length = 0;
    this->Type.m_Precision = 0;
    this->Type.m_Flags = 0;
    this->m_ValTypeID = 0;
  }
} 


Операция очистки выглядит примерно так:
Код
Выбрать все
void __thiscall CExecutedModule::OperClearFuncRetVal(CExecutedModule *this)
{
  CExecutedModule *This; // esi@1
  CType Empty; // [sp+4h] [bp-18h]@1
  int v3; // [sp+18h] [bp-4h]@1

  This = this;
  Empty.m_TypeCode = 0;
  Empty.m_Length = 0;
  Empty.m_Precision = 0;
  Empty.m_Flags = 0;
  Empty.m_TypeID = 0;
  v3 = 0;
  CValue::SetType(&this->m_FuncRetVal, &Empty);
  ++This->m_OperPos;
} 

  
Наверх
 
IP записан
 
dfuy
Junior Member
**
Отсутствует



Сообщений: 41
Зарегистрирован: 18. Марта 2013
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #11 - 04. Мая 2017 :: 14:24
Печать  
Накопал, блин. Последнее предположение подтверждается. Нашёл функцию, которую вызывает CallAsFunc. Там забавный код примерно такого типа:
Код
Выбрать все
int __thiscall CExecutedModule::CallAsFunc(CExecutedModule *this, int nMethod,
  int ParamCount, CValue **pParams, CValue *pRetVal)
{
  int result; 
  CCompileProcInfo *MethInfo;
  CValue PrevRetValue;
..............
  PrevRetValue=this->m_FuncRetVal; // Тут, как правило, лежит то самое пустое значение
..............
  MethInfo = this->m_pCompiledModule->ProcArray[nMethod];
  if ( pRetVal && MethInfo->Type == 1 ) // Type == 1 - это процедура
  {
    result = 0;
  }
  else
  {
..............
тута многа кода, вызывающего функцию
..............
    if ( MethInfo->Type == 2 && Result ) // Type == 2 - это фукция
    {
      if ( pRetVal )
        *pRetVal=this->m_FuncRetVal;
    }
    this->m_FuncRetVal=PrevRetValue; // Вот и оператор присваивания, который нифига не чистит контекст
..............
  }
  return result;
} 


Таким образом трап надо ставить не на CValue::Reset(), а на CValue::оperator=(), и там если присваиваем пустое значение, вызывать Reset, а иначе родной оператор. Попробую попозже.
« Последняя редакция: 04. Мая 2017 :: 18:46 - dfuy »  
Наверх
 
IP записан
 
vladimirmir2012
Senior Member
****
Отсутствует


1C++ rocks!

Сообщений: 426
Зарегистрирован: 18. Мая 2011
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #12 - 04. Мая 2017 :: 16:27
Печать  
.
« Последняя редакция: 13. Сентября 2018 :: 06:27 - vladimirmir2012 »  
Наверх
 
IP записан
 
dfuy
Junior Member
**
Отсутствует



Сообщений: 41
Зарегистрирован: 18. Марта 2013
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #13 - 04. Мая 2017 :: 18:40
Печать  
Да, IDA. Там HexRays Decompiler - неплохая вещь. По работе с классами там, конечно, не всё удобно. Он фактически C Decompiler, а не C++. Особенно хлопотно с виртуальными методами разбираться, но есть хитрые трюки как с его помощью и через них пробиться можно. Я про это писал тут: http://www.1cpp.ru/forum/YaBB.pl?num=1448167496
Там и ссылки есть на IDA (хотя не факт, что живые), и файлик заголовочный приложен с классами 1С, в том числе для некоторых таблицы виртуальных методов сделаны (хотя уже есть новые версии его). Если надо будет, залью.
  
Наверх
 
IP записан
 
vladimirmir2012
Senior Member
****
Отсутствует


1C++ rocks!

Сообщений: 426
Зарегистрирован: 18. Мая 2011
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #14 - 05. Мая 2017 :: 03:42
Печать  
.
« Последняя редакция: 12. Сентября 2018 :: 11:19 - vladimirmir2012 »  
Наверх
 
IP записан
 
dfuy
Junior Member
**
Отсутствует



Сообщений: 41
Зарегистрирован: 18. Марта 2013
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #15 - 05. Мая 2017 :: 16:00
Печать  
vladimirmir2012 писал(а) 05. Мая 2017 :: 03:42:
Просьба залить ...

Нашёл ссылку на тему с новой IDA 6.8: https://forum.reverse4you.org/showthread.php?t=2258
Там есть рабочие ссылки, у меня вторая же пошла. Пока не запускал ещё, не знаю чего там нового придумали. Моя текущая версию 1c_classes.h: https://yadi.sk/d/uWu8TA3v3HiSY2
Там не много изменений. Ещё структура CTypedValue должна быть добавлена тут: https://cloud.mail.ru/public/8MCv/H24MLteKK (отсюда)

PS. Вторая ссылка какая-то тормозная и не докачивается. Из 3й и 4й скачались две какие-то разные версии: обычная и Green. ХЗ чем отличаются, потом поразбираюсь.
  
Наверх
 
IP записан
 
dfuy
Junior Member
**
Отсутствует



Сообщений: 41
Зарегистрирован: 18. Марта 2013
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #16 - 05. Мая 2017 :: 20:02
Печать  
Итак, опробовал метод по навешиванию трапа на оператор присваивания. Не вдаваясь в подробности реализации перехватчиков, таким вот примерно макаром:

Код (C++)
Выбрать все
class myCValue: public CValue
{
public:
	CValue const &OperatorAssign(CValue const &Source);
};

CTrap trapOperatorAssign("bkend.dll", "??4CValue@@QAEABV0@ABV0@@Z", GetMethAddr(&myCValue::OperatorAssign));
// public: class CValue const & __thiscall CValue::operator=(class CValue const &)

CValue const &myCValue::OperatorAssign(CValue const &Source)
{
	if (Source.m_TypeCode==0) return Reset(),*this;

	CTrapSwap Swap(trapOperatorAssign);
	return (this->*trapOperatorAssign.Old(&OperatorAssign))(Source);
} 



Работает прекрасно. Причём одним махом решает все описанные проблемы (и неописанные тоже). Только вот убивает меня вешать трап на такую часто вызываемую вещь, как оператор присваивания, поскольку может сказаться на производительности, которая итак не фонтан. Есть идея слить весь его код, полностью подменив оригинальный, и поправить по собственному вкусу (опыт такой был уже, так что думаю проблем не возникнет). Займусь на досуге...

Работает, но не так уж и прекрасно. Уже объявились нюансы. Например, можно оператором присваивания затереть ссылку на исполняемый модуль. Если сделать это не с помощью пустого значения (а любого другого), трап восстановит исходную версию кода и вызовет родной оператор. Тот, в свою очередь, потрёт ссылку, модуль начнёт уничтожаться, а там объекты всякие с деструкторами. Деструкторы начнут работать, выполняя всякий код, а оператор присваивания при этом будет уже родной со всеми вытекающими... Короче, не канает такой метод, только полное дублирование кода оператора с необходимыми изменениями.
« Последняя редакция: 06. Мая 2017 :: 19:17 - dfuy »  
Наверх
 
IP записан
 
dfuy
Junior Member
**
Отсутствует



Сообщений: 41
Зарегистрирован: 18. Марта 2013
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #17 - 06. Мая 2017 :: 19:10
Печать  
Оператор присваивания успешно написан и вроде успешно работает (погонял на нескольких достаточно сложных вещах, всё работает, позже внедрю в рабочую базу, там уж точно станет ясно). Теперь точно все варианты багов исчезли. И никаких тормозов. И даже кое-что получше переписал там. Код приводить не буду, ибо он сильно завязан на моих наработках, которых нет в стандартном наборе 1CHEADERS из 1С++. Но могу скомпилить в виде отдельной dll-ки. Достаточно её подгрузить в 1С и оператор присваивания заработает как ему положено.

Обновил 1c_classes.h, ссылка та же. Теперь там много изменений. Я по пути ещё прикольные вещи раскопал. Давно мечтал получить информацию о наличии у параметров методов значения по умолчанию, ибо исполняемый модуль, а как следствие и объекты ООП, не могли вызывать методы с параметрами по умолчанию. Было очень неудобно. Теперь такой проблемы нет: вот такой код
Код (C++)
Выбрать все
CCompiledProcDescr &Proc=*pIntInfo->pCompiledModule->ProcArray[Index];
CString Text(Proc.Name);
Text+='(';
for (int n=0;n<Proc.NParams;n++)
{
	CCompiledProcVarDescr &Var=*Proc.VarList[n];
	if (n) Text+=',';
	Text+=Var.Name;
	if (Var.DefValuePos<0) continue;

	Text+='=';
	CCompiledConstDescr &Const=*pIntInfo->pCompiledModule->ConstArray[Var.DefValuePos];
	if (Const.Value.m_TypeCode==STRING_TYPE_1C) Text+='"'; else
	if (Const.Value.m_TypeCode==DATE_TYPE_1C) Text+='\'';
	Text+=Const.Value.Format();
	if (Const.Value.m_TypeCode==STRING_TYPE_1C) Text+='"'; else
	if (Const.Value.m_TypeCode==DATE_TYPE_1C) Text+='\'';
}
Text+=')';
 

позволяет получить всю информацию о параметрах метода, включая значения по умолчанию. Вот мои 1cheaders, с которыми он вроде с ходу должен заработать.
  
Наверх
 
IP записан
 
vladimirmir2012
Senior Member
****
Отсутствует


1C++ rocks!

Сообщений: 426
Зарегистрирован: 18. Мая 2011
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #18 - 07. Мая 2017 :: 04:00
Печать  
.
« Последняя редакция: 13. Сентября 2018 :: 06:26 - vladimirmir2012 »  
Наверх
 
IP записан
 
vladimirmir2012
Senior Member
****
Отсутствует


1C++ rocks!

Сообщений: 426
Зарегистрирован: 18. Мая 2011
Re: Очередной глобальный баг 1С, мешающий использованию ООП (и не только)
Ответ #19 - 07. Мая 2017 :: 05:24
Печать  
.
« Последняя редакция: 13. Сентября 2018 :: 06:26 - vladimirmir2012 »  
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: [1] 
ОтправитьПечать