C ++ слияние 2 wchar_t * - PullRequest
       2

C ++ слияние 2 wchar_t *

0 голосов
/ 14 июня 2019

У меня интересная проблема, и я не знаю, почему.

inline void mergeWChar(wchar_t*& dest, const wchar_t* source) {
    if (dest == nullptr) {
        dest = const_cast<wchar_t*>(source);
        return;
    }
    int size = wcslen(dest);
    wcscat_s(dest, size, source);
}
inline void test() {
    wchar_t* msg = nullptr;
    wchar_t* t = L"BLA.BLA.BLA";
    mergeWChar(msg, L"Ts is jut a phrase in order to test my function");
    mergeWChar(msg, t);
}

Я пытаюсь создать функцию, которая будет объединять более жесткие 2 wchar_t *, используя функцию wcscat_s, но по какой-то причине не работает, и я получаю это сообщение об ошибке.

Исключение, выданное в 0x5D8C3A18 (ucrtbased.dll) в ConsoleApplication1.exe: 0xC0000005: Место записи нарушения прав доступа 0x0082DD60.

Кроме того, я уже проверил эти 2 вопроса и мне это не очень помогло.

Проблема wcscat_s

Функция wcscat_s - ошибка буфера

ЧТО Я НЕ МОГУ ДЕЛАТЬ

Я работаю с устаревшим кодом и могу НЕ использовать такие вещи, как:

  1. wstring
  2. to_wstring
  3. wchar_t var [size] <- это не сработает. </li>

1 Ответ

1 голос
/ 14 июня 2019

Здесь:

mergeWChar(msg, t);

msg указывает на строковый литерал L"Ts is jut a phrase in order to test my function". Вы не можете изменить строковый литерал.

Вы хотите это:

inline void mergeWChar(wchar_t*& dest, const wchar_t* source) {
  if (dest == nullptr) {
    dest = const_cast<wchar_t*>(source);
    return;
  }

  wchar_t *newdest = (wchar_t*)malloc((wcslen(dest) + wcslen(source) + 1) * sizeof *newdest);
  wcscpy(newdest, dest);      // the *_s functions are useless here
  wcscat(newdest, source);    // as you know that newdest point to
                              // a long enough buffer
  dest = newdest;
}

Отказ от ответственности: здесь не делается проверка ошибок для краткости.

Источником проблемы является плохой дизайн функции mergeWChar и сомнительное использование const_cast<wchar_t*>, которое в основном позволяет назначить указатель на постоянную строку для обычного указателя, что затем позволяет изменить это постоянная память, которая в конечном итоге выходит из строя.

Однако есть проблема с этим дизайном: вы не можете освободить выделенную память, потому что указатель dest не обязательно является указателем, который был получен через malloc. Поэтому следующий дизайн лучше ИМО:

inline void mergeWChar(wchar_t*& dest, const wchar_t* source) {
  int size = (dest ? wcslen(dest) : 0) + wcslen(source) + 1;
  wchar_t *newdest = (wchar_t*)malloc(size * sizeof *newdest);
  if (dest)
    wcscpy(newdest, dest);
  else
    newdest[0] = 0;
  wcscat(newdest, source);
  dest = newdest;
}

Таким образом, нет никакого уродливого приведения и нет риска неконстантного указателя, указывающего на постоянную память, и вы можете быть уверены, что указатель, модифицированный mergeWChar, может быть освобожден, несмотря ни на что. Стоимость в том, что вам нужно больше памяти.

Пример использования:

...
wchar_t* msg = nullptr;
wchar_t* t = L"BLA.BLA.BLA";
mergeWChar(msg, L"Ts is jut a phrase in order to test my function");
mergeWChar(msg, t);
...
free(msg);
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...