Использование умных указателей - PullRequest
1 голос
/ 31 мая 2019

Я работаю над устаревшим приложением C ++, которое имеет следующую функцию:

char* CreateNewString (const char* node)
{
   int len = (int) strlen(node) + 1;
   char * ptr = new char [len];
   strcpy_s(ptr, len, node);
   return ptr;
}

Эта функция вызывается из многих классов в приложении, и вот пример использования.

char * nodeID = obj.CreateNewString(process->GetNodeID());

Приложение вызывает другой процесс и получает идентификатор узла в виде указателя на символ, а затем передает его в функцию CreateNewString для динамического выделения памяти для новой строки.

Нигде в приложении послеВызов выше, это удаление памяти.Из того, что я наблюдаю, здесь есть определенная утечка памяти.

Я думаю, что есть несколько способов решить эту проблему.Но я хочу изучить использование интеллектуальных указателей в C ++ 11, прежде чем пытаться что-либо еще.

То, что я пытался:

Итак, я придумал следующую функцию:

  char* CreateNewString (const char* node) 
  {
       int len = (int) strlen(node) + 1;
       shared_ptr<char> ptr (new char [len](), [](char* p) {delete [] p;});
       strcpy_s(ptr.get(), len, node);
       return ptr.get();
    }

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

Выше приведеноне работает, поскольку ptr выпущено, поскольку оно объявлено внутри области действия этой функции.

Моя цель:

  1. Использовать умные указатели C ++ 11 для достижения этой цели.с минимальными изменениями кода в существующем приложении.

Другой известный мне способ - это динамическая инициализация массива в самих вызывающих местах, а затем удаление его до конца этой области.Но я хочу изучить новые возможности C ++, прежде чем вернуться к традиционному способу C ++.Кстати, я не заинтересован в изучении std::string на данный момент.

Ответы [ 3 ]

6 голосов
/ 31 мая 2019

Вы могли бы:

  • вернуть shared_ptr
  • вернуть std::string
  • оставь все как есть

Это ваши варианты.

3 голосов
/ 04 июня 2019

Я не вижу способа, чтобы вы могли заставить функцию возвращать указатель на символ и при этом использовать умные указатели. Могут быть потенциальные взломы при получении этого, но у всех есть накладные расходы и, что более важно, ненужный код. Я предлагаю сделать простое изменение новой функции, которую вы написали, а затем сделать еще одно еще более простое изменение во всех вызывающих местах.

Итак, функция будет выглядеть так:

 shared_ptr<char> CreateNewString (const char* node) 
  {
       int len = (int) strlen(node) + 1;
       shared_ptr<char> ptr (new char [len](), [](char* p) {delete [] p;});
       strcpy_s(ptr.get(), len, node);
       return ptr;
  }

И затем, где бы он ни вызывался, просто добавьте .get ()

char * nodeID = obj.CreateNewString(process->GetNodeID()).get();
1 голос
/ 31 мая 2019

Это своего рода хак, но он будет работать, и у вас не будет утечки памяти.Что вы можете сделать, это добавить статический вектор интеллектуальных указателей, а затем, когда вы вызываете функцию, вы сохраняете указатель в векторе, чтобы он не выходил из области видимости в конце функции.Это выглядело бы как

char* CreateNewString (const char* node) 
{
    std::size_t len = strlen(node) + 1;
    static std::vector<std::unique_ptr<char[]>> data_pool; // static pool, destroyed at end of program
    data_pool.push_back(std::unique_ptr<char[]>(new char [len]{})); // add pointer to pool
    strcpy_s(data_pool.back().get(), len, node); // copy the string
    return data_pool.back().get(); // return pointer to the managed data
}

с использованием std::unique_ptr, который правильно удаляет массивы, поэтому нам не нужно пользовательское средство удаления

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...