簡體   English   中英

如何加倍數組大小(第二次出錯)

[英]how to double array size (error on second time)

這里有一些幫助,試圖在 cpp 中加倍數組

在第二次調整大小時我得到了這個(混亂的輸出)

% ./sample
[5] 1 2 3 4 5 
[20] 1 2 3 4 0 6 7 -1610612736 1 2 3 4 14 0 0 0 0 -1610612736 0 0 

同樣刪除內存集(將剩余位置歸零)

#include <iostream>
#include <cstdlib>

using namespace std;

void resize(int* v, int* size){ // double the array size
    int newSize = (*size) * 2;
    v = (int *) realloc(v, (size_t) newSize);
    memset(v+(*size), 0, sizeof(int) * (newSize - *size) );
    *size = newSize;
}

int main(){
    int size = 5;
    int* v = new(nothrow) int[size]();

    v[0] = 1; v[1] = 2; v[2] = 3; v[3] = 4; v[4] = 5;

    cout << "[" << size << "] ";
    for(int i = 0; i < size; i++) cout << v[i] << " "; cout << endl;

    resize(v, &size);
    resize(v, &size);   // <- messy output

    v[5] = 6; v[6] = 7;

    cout << "[" << size << "] ";
    for(int i = 0; i < size; i++) cout << v[i] << " "; cout << endl; 

    return 0;
}

謝謝您的幫助,

malloc()realloc()newdelete[]一起使用 - 不能同時使用

您的直接問題是您將指針傳遞給 function 並且 function 收到一個副本 - 因此對 function 中的v所做的任何更改都會對指針的本地副本進行(它有自己的地址並且與指針v非常不同在main()

另一個問題是混合使用newrealloc() ,這會導致未定義的行為。 main()中使用malloc() ) 或使用new在您的 function 中手動創建和復制,並在分配新塊之前在原始對象上調用delete[]

由於這是 C++,您可以通過將指針引用傳遞給 function(例如int*& v )來輕松解決問題,因此realloc()對原始指針地址而不是副本進行操作。

注意:正如 JL 在評論中提到的,每當您調用realloc()時,您必須將結果分配給一個臨時指針,您在分配給原始指針之前驗證realloc()是否成功。 當(不是如果) realloc()失敗時,它將返回NULL並用 NULL 覆蓋您的原始指針,從而使NULL的塊無法釋放,從而造成 memory 泄漏。

要將臨時指針與realloc()一起使用,您可以這樣做:

void resize(int*& v, int *size){ // double the array size
    int newSize = (*size) * 2;
    
    /* always realloc with temporary pointer so if realloc fails
     * you don't overwrite your orignal pointer with NULL creating
     * a memory leak.
     */
    int *tmp = (int *)realloc (v, (size_t) newSize * sizeof *v);
    if (!tmp) {   /* validate every allocation */
        perror ("realloc-v");
        return;
    }
    v = tmp;      /* successful realloc(), assign tmp to v */
    
    memset (v+(*size), 0, sizeof(int) * *size );
    *size = newSize;
}

此外,在main()中要使用realloc() ,您最初必須使用malloc() (或calloc()realloc() ,但不是new )進行分配。 此外,保護您的循環范圍,或者如果您不打算使用{...}保護 scope,那么至少適當縮進以便您的意圖明確,例如

int main(){
    int size = 5;
    int *v = (int*)malloc(size * sizeof *v);

    v[0] = 1; v[1] = 2; v[2] = 3; v[3] = 4; v[4] = 5;

    cout << "[" << size << "] ";
    for (int i = 0; i < size; i++)
        cout << v[i] << " ";
    cout << endl;

    resize(v, &size);
    resize(v, &size);

    if (size > 6) {     /* validate size / protect memory bounds */
        v[5] = 6;
        v[6] = 7;
    }
    
    cout << "[" << size << "] ";
    for (int i = 0; i < size; i++)
        cout << v[i] << " ";
    cout << endl; 

    return 0;
}

(您還應該為memset()添加#include <cstring>

使用newdelete[]

如果您使用new在 function 中創建一個大小加倍的新塊,則可以將分配保留在main()中,將值復制到新塊(並將 rest 初始化為0 )並在原始塊上調用delete[]在將新塊分配給原始指針之前阻塞。

在那種情況下,你會做類似的事情:

void resize(int*& v, int *size){ // double the array size
    int newSize = (*size) * 2;
    
    /* create a new block of newSize */
    int *tmp = new(nothrow) int[newSize]();
    /* copy/initialize */
    for (int i = 0; i < newSize; i++) {
        if (i < *size)
            tmp[i] = v[i];
        else
            tmp[i] = 0;
    }
    delete[] v;   /* free original block */
    v = tmp;      /* assign tmp to v */
    
    *size = newSize;
}

示例使用/輸出

在任一情況下( malloc()realloc() )或( newdelete[] ),結果都是相同的:

$ ./bin/realloc_arr
[5] 1 2 3 4 5
[20] 1 2 3 4 5 6 7 0 0 0 0 0 0 0 0 0 0 0 0 0

在這兩種情況下,您都需要驗證您的 memory 使用valgrind或類似的 memory 使用/錯誤檢查您的操作系統。 您需要在main()的末尾添加free(v)delete[] v來處理釋放您為 memory 檢查目的分配的所有 883933302533388(它將在程序退出后釋放,但沒有明確說明在main()中釋放它仍然會在程序退出時顯示為正在使用。

要使用 valgrind,只需通過它運行您的程序。 進行上述更改后,您將擁有:

$  valgrind ./bin/realloc_arr
==22674== Memcheck, a memory error detector
==22674== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==22674== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==22674== Command: ./bin/realloc_arr
==22674==
[5] 1 2 3 4 5
[20] 1 2 3 4 5 6 7 0 0 0 0 0 0 0 0 0 0 0 0 0
==22674==
==22674== HEAP SUMMARY:
==22674==     in use at exit: 0 bytes in 0 blocks
==22674==   total heap usage: 5 allocs, 5 frees, 73,868 bytes allocated
==22674==
==22674== All heap blocks were freed -- no leaks are possible
==22674==
==22674== For counts of detected and suppressed errors, rerun with: -v
==22674== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

始終確保釋放所有塊並且沒有 memory 錯誤。

供參考工作版本

#include <iostream>
using namespace std;

void resize(int*& v, int* size){ // double the array size
    int newSize = (*size) * 2;
    int* tmp = new(nothrow) int[newSize]();  // zeroing on the next line is redundant?
    for(int i = 0; i < newSize; i++) tmp[i] = (i < *size) ? v[i] : 0;
    delete[] v;
    v = tmp; 
    *size = newSize;
}

int main(){
    int size = 5;
    int* v = new(nothrow) int[size]();

    v[0] = 1; v[1] = 2; v[2] = 3; v[3] = 4; v[4] = 5;

    cout << "[" << size << "] ";
    for(int i = 0; i < size; i++) cout << v[i] << " "; cout << endl;

    resize(v, &size);
    resize(v, &size);   // <- NOW, working output
    //resize(v, &size);

    v[5] = 6; v[6] = 7;

    cout << "[" << size << "] ";
    for(int i = 0; i < size; i++) cout << v[i] << " "; cout << endl; 

    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM