Сбой при попытке динамически изменить размер массива в C ++? - PullRequest
0 голосов
/ 07 февраля 2012

Сейчас я хочу увеличить размер массива с помощью функции.

#include <iostream>
using namespace std;

void IncreaseArraySize(int* addr){
    int* temp = new int[20];
    for(int i=0;i<10;i++){
        temp[i] = addr[i];
    }
    for(int i=10;i<20;i++){
        temp[i] = i;
    }
    int* dummy = addr;
    addr = temp;
    delete[] dummy;
}

int main(){
    int* test = new int[10];
    for(int i=0;i<10;i++){
        test[i] = i;
    }
    IncreaseArraySize(test);
    for(int i=0;i<20;i++){
        cout<<"at index "<<i<<"we have"<<test[i]<<endl;
    }
    cout<<"ok!"<<endl;
    delete[] test;
}

Я запустил код с помощью: valgrind --leak-check = full ./test 2> debug.txt

и вот что я получил за вывод:

at index 0we have0
at index 1we have1
at index 2we have2
at index 3we have3
at index 4we have4
at index 5we have5
at index 6we have6
at index 7we have7
at index 8we have8
at index 9we have9
at index 10we have0
at index 11we have0
at index 12we have0
at index 13we have0
at index 14we have0
at index 15we have0
at index 16we have0
at index 17we have0
at index 18we have112
at index 19we have0
ok!

и вот что я получил по debug.txt:

==4285== Memcheck, a memory error detector
==4285== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==4285== Using Valgrind-3.6.1-Debian and LibVEX; rerun with -h for copyright info
==4285== Command: ./test
==4285== 
==4285== Invalid read of size 4
==4285==    at 0x400997: main (test.cpp:24)
==4285==  Address 0x596f040 is 0 bytes inside a block of size 40 free'd
==4285==    at 0x4C27C6E: operator delete[](void*) (vg_replace_malloc.c:409)
==4285==    by 0x400931: IncreaseArraySize(int*) (test.cpp:14)
==4285==    by 0x400980: main (test.cpp:22)
==4285== 
==4285== Invalid free() / delete / delete[]
==4285==    at 0x4C27C6E: operator delete[](void*) (vg_replace_malloc.c:409)
==4285==    by 0x400A16: main (test.cpp:27)
==4285==  Address 0x596f040 is 0 bytes inside a block of size 40 free'd
==4285==    at 0x4C27C6E: operator delete[](void*) (vg_replace_malloc.c:409)
==4285==    by 0x400931: IncreaseArraySize(int*) (test.cpp:14)
==4285==    by 0x400980: main (test.cpp:22)
==4285== 
==4285== 
==4285== HEAP SUMMARY:
==4285==     in use at exit: 80 bytes in 1 blocks
==4285==   total heap usage: 2 allocs, 2 frees, 120 bytes allocated
==4285== 
==4285== 80 bytes in 1 blocks are definitely lost in loss record 1 of 1
==4285==    at 0x4C2864B: operator new[](unsigned long) (vg_replace_malloc.c:305)
==4285==    by 0x4008A9: IncreaseArraySize(int*) (test.cpp:5)
==4285==    by 0x400980: main (test.cpp:22)
==4285== 
==4285== LEAK SUMMARY:
==4285==    definitely lost: 80 bytes in 1 blocks
==4285==    indirectly lost: 0 bytes in 0 blocks
==4285==      possibly lost: 0 bytes in 0 blocks
==4285==    still reachable: 0 bytes in 0 blocks
==4285==         suppressed: 0 bytes in 0 blocks
==4285== 
==4285== For counts of detected and suppressed errors, rerun with: -v
==4285== ERROR SUMMARY: 22 errors from 3 contexts (suppressed: 4 from 4)

Не могли бы вы объяснить это?в терминах новичка?

Ответы [ 2 ]

3 голосов
/ 07 февраля 2012

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

void IncreaseArraySize(int*& addr){

Прямо сейчас, ваша ошибка вызвана, потому что, когда вы звоните

IncreaseArraySize(test);

Указатель test обратно в main не переназначается. В результате, как только вы delete[] это в IncreaseArraySize, он ссылается на мусорную память. Обновление параметра таким образом, чтобы он передавался по ссылке, означает, что когда в IncreaseArraySize вы говорите

addr = temp;

Это обновит указатель test в main, предотвращая ошибку.

Надеюсь, это поможет!

3 голосов
/ 07 февраля 2012

Ну, самый подходящий способ исправить этот код - вообще не использовать new, просто используйте:
станд: вектор

Кроме того, проблема с вашим кодом, в частности, заключается в том, что вы передаете указатель addr по значению, который создает временный объект и передает его функции. Любые изменения, внесенные в этот указатель внутри функции, выполняются на копии указателя, а не на исходном указателе. Вам нужно addr по ссылке, чтобы изменения внутри функции были сделаны для указателя и отражались вне функции.

void IncreaseArraySize(int*& addr)
...