S
S
StillDontKnowMyName2020-05-08 15:04:28
C++ / C#
StillDontKnowMyName, 2020-05-08 15:04:28

How to optimize writing classes from memory?

The task was quite simple: the dll loaded into the process should read the class data stored there from the process memory and arrange them.

In this task, we do not have the opportunity to do this on the process side, everything must be done by a loadable dll, but in the process there is a function that can be called from a dll that returns a pointer to the first class in the list, with each class (except the last) containing a pointer to the next class. Here's what the class looks like:

class ClientClass
{
public:
  const char* m_pNetworkName;
  Table* m_pTable;
  ClientClass* m_pNext;
};


Tablein turn, it is also a class and it contains structures that store information about class members - Prop:

struct Table
{
  Prop* m_pProps;              // Указатель на массив Prop'ов
  int m_iProps;                   // количество Prop в Table
  char* m_pNetTableName;
};

struct Prop
{
  char* m_pVarName;      // название члена класса
  Table* m_pDataTable;
  int m_Offset;                // смещение указателя Prop относительно указателя Table
};


Pay attention to the fact that it Propmay be inside Table, the information from which you also need to read.

You need to read memory for two purposes: writing information to a text file and storing it in statically allocated dll memory for later use.

My implementation of writing to a text file (the LOG macro writes string to a text file from a new line):

std::vector<std::string> base_classes;
static int class_level{ 0 };

void WriteAllOffsetsInLog()
  {
    // получаем указатель на первый класс
    auto cl_class = Cl->GetFirstClass();
    if (!cl_class)
      return;

    // сохраняем имена основных классов, чтобы не перечислять их члены в дочерних классах
    while (cl_class)
    {
      auto table = cl_class->m_pTable;

      if (table && table->m_iProps)
        base_classes.push_back(table->m_pNetTableName);

      cl_class = cl_class->m_pNext;
    }

    // снова находим первый класс
    cl_class = Cl->GetFirstClass();
    if (!cl_class)
      return;

    while (cl_class)
    {
      auto table = cl_class->m_pTable;

      if (table && table->m_iProps)
      {
        class_level = 1;
        // эта функция работает со структурами table и props
        WriteClass(table, cl_class->m_pNetworkName);
      }

      cl_class = cl_class->m_pNext;
    }
  }

  void WriteClass(Table* table, std::string name, int off = 0)
  {
    // добавляем табы в строчку в зависимости от того, насколько глубоко расположен класс в общем дереве
    std::string tabtab = std::string();
    for (int w = 0; w < class_level - 1; w++)
      tabtab += "    ";

    std::string define_class { tabtab };
    define_class += "class    ";
    define_class += name;

    for (int i = 0; i < table->m_iProps; i++)
    {
      auto prop = table->m_pProps[i];
      // перечисляем включённые классы справа от имени дочернего
      if (prop.m_Offset == NULL && prop.m_pDataTable && prop.m_pDataTable->m_iProps && IsBaseClass(prop.m_pDataTable))
      {
        define_class += "  :  public ";
        define_class += prop.m_pDataTable->m_pNetTableName;
      }
    }

    if (off)   // указатель класса смещён относительно материнского класса
    {
      define_class += "    //        ";
      define_class += to16(off);
    }

    LOG(define_class);
    LOG(tabtab + "{");
    LOG(tabtab + "public:");

    записываем члены класса
    for (int i = 0; i < table->m_iProps; i++)
    {
      auto intabtab = tabtab + "    ";

      auto prop = table->m_pProps[i];

      auto offset = to16(prop.m_Offset);

      auto new_table = prop.m_pDataTable;
      if (new_table) // член класса оказался классом и нужно вызвать функцию, которая запишет члены этого класса
      {
        if (!prop.m_Offset && IsBaseClass(new_table)) // оказалось, это не член класса, а включённый класс который будет расписан отдельно
          continue;

        if (new_table->m_iProps)
        {
          class_level++;
          WriteClass(new_table, new_table->m_pNetTableName, prop.m_Offset);
          class_level--;
        }
      }
      else if (prop.m_Offset) // это просто переменная, запишем её смещение указателя
      {
        std::string log = intabtab;

        log += "uintptr_t    ";
        log += prop.m_pVarName;
        log += " = ";
        log += offset;
        log += ";";
        LOG(log);
      }
    }

    LOG(tabtab + "};");
    LOG("");

    if (class_level == 1)
      LOG("");
  }


Can you please tell me how to optimize this code? It is not optimized from the word at all, profiling revealed that operations with std::vector take the most time.

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question