0

Recently I want to convert vector to char* array[].

So I had found the solution. But It was not safety way..

Here is my code

char** arr = new char* [4];

vector<string> vv;

// setting strings
for (int i = 0 ;i < 4; i++)
{
    vv.emplace_back("hello world");
}
// convert
for (int i = 0; i < 4; i++)
{
    arr[i] = new char[vv[i].size()];
    memcpy(arr[i], vv[i].c_str(), vv[i].size());
}

// prints
for (int i = 0; i < 4; i++)
{
    cout << arr[i] << endl;
}

// output
// hello world羲羲?솎솨
// hello world羲羲拂솽솨
// hello world羲羲
// hello world羲羲?펺솨

// delete memorys
for (unsigned index = 0; index < 4; ++index) {
    delete[] arr[index];
}

delete []arr;

Why does it happen string crash?? Is there no safe way anymore?

T Eom
  • 85
  • 1
  • 2
  • 11
  • 1
    When printing string pointed by a `const char*` pointer, the string must be null-terminated so the program knows the length of the string. The size returned by `std::string::size` does not include the null character, so this is the reason for the unexpected characters. You should allocate one more character and set it to NULL for each array pointed by `char*`. – paxbun Nov 14 '19 at 05:04
  • @paxhun if vector's size is 11 and capacity is 14. So you mean 3 null characters were included. Right? – T Eom Nov 14 '19 at 05:06
  • 1
    If the size of the vector is 11, that means there are 11 strings, so you have to put 11 additional NULL characters. The vector's capacity does not matter here. – paxbun Nov 14 '19 at 05:11

3 Answers3

1

When you use memcpy, arr[i] is not guaranteed to be a null-terminated string. To treat arr[i] as null terminated string, as in

cout << arr[i] << endl;

causes undefined behavior.


You need couple of minor changes.

  1. Allocate one more byte of memory.
  2. Use strcpy instead of memcpy.
arr[i] = new char[vv[i].size() + 1];
strcpy(arr[i], vv[i].c_str());
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • but visual studio error : 'this function may be unsafe' So it recommend using strcpy_s... – T Eom Nov 14 '19 at 05:04
  • @TEom, sure you can use that or `strncpy`. – R Sahu Nov 14 '19 at 05:05
  • 2
    To be honest, even memcpy would work if you remember that [C strings are always null terminated](https://stackoverflow.com/questions/12697788/does-stdstringc-str-always-return-a-null-terminated-string). You just have to allocate size+1 and also copy size+1. – Maciej Załucki Nov 14 '19 at 05:09
  • @MaciejZałucki, agreed. That is also another option. – R Sahu Nov 14 '19 at 05:10
0

There's an easier way of doing this if you can maintain the lifetime of your initial vector.

for (int i = 0; i < 4; i++)
{
    arr[i] = vv[i].c_str();
}

This way you won't allocate no additional memory, however, you'd have to keep in mind that once your initial vector gets destroyed, that array will be corrupted as well. But if you need such conversion for some simple synchronous api call within the same thread, that would do the trick.

Denis Sheremet
  • 2,453
  • 2
  • 18
  • 34
0

In such cases I usually use this ugly construct.

arr[i] = new char[vv[i].size() + 1];
arr[i][vv[i].copy(arr[i], vv[i].size())] = 0;
Maciej Załucki
  • 464
  • 1
  • 4
  • 15