繁体   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