Почему у меня во время выполнения возникает ошибка динамического выделения памяти (кучи)? - PullRequest
2 голосов
/ 19 марта 2012

Моя программа испытывает ошибку времени выполнения каждый раз, когда я раскомментирую l70-72.Я не впервые сталкиваюсь с этой конкретной проблемой.

Я делаю указатель на массив объектов, отправляю этот указатель в функцию, пытаюсь выполнить команды, определенные в этой функции, в main и получить время выполненияошибка, все при использовании кучи.Что-то явно происходит с этим указателем или с указателями в массиве.

Когда я вызываю manage_Rectangle_arr(string strCommand, Rectangle * *arr, short *siArrayL), возникает ошибка с любым из следующих: «заполнить массив», «получить области» и «пустое содержимое»(очевидно, что последние два связаны с «заполнением массива» по своей природе, так как им нужно, чтобы он выполнялся первым, чтобы функционировать)

void manage_Rectangle_arr(string, Rectangle * *, short*);

int main()
{
    Rectangle * * arr;
    short siArrayL=1;

    manage_Rectangle_arr("make array", arr, &siArrayL);
    manage_Rectangle_arr("fill array", arr, &siArrayL); //Problem here
    manage_Rectangle_arr("get areas", arr, &siArrayL); //Problem here
    manage_Rectangle_arr("empty contents", arr, &siArrayL); //Problem here
    manage_Rectangle_arr("delete array", arr, &siArrayL);
}

void manage_Rectangle_arr(string strCommand, Rectangle * *arr, short *siArrayL)
{
    if(strCommand=="make array")
    arr = new Rectangle * [ *siArrayL];

    if(strCommand=="fill array") //Problem here
    for(short s=0; s< *siArrayL; ++s)
    arr[s]= new Rectangle(1, 1);

    if(strCommand=="get areas") //Problem here
    for(short s=0; s< *siArrayL; ++s)
    cout << arr[s]->getArea();

    if(strCommand=="empty contents") //Problem here
    for(short s=0; s< *siArrayL; ++s)
    delete arr[s];

    if(strCommand=="delete array")
    delete [] arr;
}

//When I call manage_Rectangle_arr(string strCommand, Rectangle * *arr, short *siArrayL) with any of the following: "fill array", "get areas" and "empty contents" (obviously the last two are related to "fill array" in nature, since they need it to be executed first in order to function)

Полный исходный код C ++

Ответы [ 2 ]

3 голосов
/ 19 марта 2012

По сути, в этом коде есть две ошибки, помимо проблемы с оплатой по значению, на которую указал Макс.

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

Вторая ошибка: вы используете указатели . Каждый курс C ++ понимает это неправильно. Указатели не имеют места в большинстве кода C ++. Не принимайте вредных привычек.

Исправленный и упрощенный код должен выглядеть следующим образом:

int main()
{
    short siArrayL=1;
    std::vector<Rectangle> arr(siArrayL);

    fill_array(arr);
    print_areas(arr);
}

С помощью двух методов:

void fill_array(std::vector<Rectangle>& arr) {
    for (std::vector<Rectangle>::iterator i = arr.begin(); i != arr.end(); ++i)
        *i = Rectangle(1, 1);
}

void print_areas(std::vector<Rectangle> const& arr) {
    for (std::vector<Rectangle>::const_iterator i = arr.begin(); i != arr.end(); ++i)
        std::cout << i->getArea();
}

Обратите внимание, в частности, на то, что больше нет необходимости использовать «пустое содержимое» и «удалять массив». Только два преимущества от использования указателей.

1 голос
/ 19 марта 2012

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

Ваш массив имеет тип Rectangle**, то есть указатель на указатель на прямоугольник.Вы отправляете это по значению в метод.Это означает, что значение arr в исходном методе будет скопировано в переменную arr в manage_Rectangle_arr.Таким образом, когда вы присваиваете arr значение (адрес области памяти / массива new), arr будет содержать это значение только в вызываемой функции - так как это совершенно разные переменные.

Есливместо этого вы объявляете manage_Rectangle_arr как

void manage_Rectangle_arr(string strCommand, Rectangle * * &arr, short *siArrayL)

Эта переменная / область памяти будет отправлена ​​по ссылке, что означает, что это будет другой, автоматический уровень косвенности.Вы можете сделать это, имея переменную типа Rectangle *** и разыменовав переменную arr, но это быстро становится глупым.

В вашем коде также есть много других «не лучших практик»,но я не буду говорить о них всех здесь.:) Надеюсь, это поможет вам вернуться на правильный путь!

...