Доступ и изменение 2D динамически размещаемых массивов - PullRequest
0 голосов
/ 09 апреля 2020

Я пытаюсь создать двумерный массив c -строк (для конкретного школьного упражнения c; я вынужден использовать c -строки для практики), используя динамическое распределение памяти c. Однако, похоже, что при доступе ко второму индексу массива (второму подмассиву) и записи в него фактическая используемая область памяти совпадает с первым индексом.

Код:

#include <iostream>
#include <string>
int main()
{
int n_names; std::string current; const int SPACE_FOR_EACH_NAME = 100;
std::cout << "How many names to input? "; std::cin >> n_names; std::cin.ignore();

//dynamically allocate a multi-dimensional array
char** names;
names = new char* [n_names];
for (int i = 0; i < n_names; i++)
    names[i] = new char[SPACE_FOR_EACH_NAME];

int count = 0;
while (count < n_names) {
    std::cout << "Name " << ++count << ": ";
    std::getline(std::cin, current);
    names[count-1] = (char*) current.c_str(); //THE TROUBLE SEEMS TO BE HERE
}

for (int i = 0; i < n_names; ++i) {
    for (int j = 0; j < SPACE_FOR_EACH_NAME; ++j) {
        if (names[i][j] == '\0') break; //termination of the current name
        std::cout << names[i][j];
    }
    std::cout << "\n";
}

//free allocated memory
for (int i = 0; i < n_names; ++i)
    delete[] names[i];
delete[] names;
}

Что показывает отладчик при изменении массива 'names' (рассмотрим вводимые пользователем 2 имени):

+       names[count-1]  0x00affbe8 "dude"   char * //here count is 1
+       names[count-1]  0x00affbe8 "noice"  char * //here count is 2

И консоль просто выводит "noice" дважды. Что не так?

1 Ответ

0 голосов
/ 09 апреля 2020

Результат current.c_str() никогда не должен храниться какое-то время. Это неопределенное поведение, но вполне вероятно, что здесь указанная память будет использоваться повторно.

Вы помещаете char * из current.c_str() в names[0], а затем добавляете новое значение в current и положить current.c_str() в names[1]. Но поскольку вы изменили current, вы также измените names[0].

Кроме того, в обоих случаях вы отбрасываете созданный вами указатель с помощью names[i] = new char[SPACE_FOR_EACH_NAME];

. Это выделяет блок памяти и помещает его адрес в names[0] (0 в качестве конкретного примера c). Следующее, что происходит с names[0], это names[0] = (char*) current.c_str();, который помещает другой адрес в переменную. Адрес, возвращаемый из new, полностью теряется, что приводит к утечке памяти.

Вместо

names[count-1] = (char*) current.c_str();

try

std::strcpy(names[count-1],current.c_str())
...