带有指向数组的指针的过程重新分配

Procedural realloc with pointer to an array

本文关键字:新分配 分配 指针 数组 过程      更新时间:2023-10-16

为了保持代码整洁(而且过于复杂,就像我所做的那样),我希望main()函数将指向int/数组的/指针传递给函数。然后,该函数将按程序扩展数组并添加与条件匹配的新条目。

我有一个有效的代码,但由于某种原因valgrind报告内存泄漏(来自主数组)。而且,我不喜欢在重新分配数组之前必须如何分配数组。

#include <iostream>
#include <cstdlib>
int get_divisors(int num_input, int *num_result);
int main()
{
    int num_input, *num_result = (int*)malloc(sizeof(int));
    std::cin >> num_input;
    int num_size = get_divisors(num_input, num_result);
    for (int loop_1 = 0; loop_1 < num_size; loop_1++){
        std::cout << num_result[loop_1] << "n";
    }
    free(num_result);
}
int get_divisors(int num_input, int *num_result)
{
    int num_count = 0;
    for (int loop_1 = 1; loop_1 < num_input; loop_1++){
        if (num_input % loop_1 == 0){   
            num_count++;
            num_result = (int*)realloc(num_result, num_count*sizeof(int));
            num_result[num_count - 1] = loop_1;
        }
    }
    return num_count;
}

瓦尔格林德: (--泄漏检查=完整 --显示泄漏种类=所有 -v)

==13337== HEAP SUMMARY:
==13337==     in use at exit: 72,724 bytes in 2 blocks
==13337==   total heap usage: 7 allocs, 6 frees, 72,768 bytes allocated
==13337== 
==13337== Searching for pointers to 2 not-freed blocks
==13337== Checked 123,368 bytes
==13337== 
==13337== 20 bytes in 1 blocks are definitely lost in loss record 1 of 2
==13337==    at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13337==    by 0x400A0A: get_divisors(int, int*) (in /media/areuz/Storage - Linux/1 :: Documents/Programming/2 :: C++ Language/1 :: C++ Codes/Divisibility Check/divisibility)
==13337==    by 0x400964: main (in /media/areuz/Storage - Linux/1 :: Documents/Programming/2 :: C++ Language/1 :: C++ Codes/Divisibility Check/divisibility)
==13337== 
==13337== 72,704 bytes in 1 blocks are still reachable in loss record 2 of 2
==13337==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13337==    by 0x4E9B2AF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==13337==    by 0x4010139: call_init.part.0 (dl-init.c:78)
==13337==    by 0x4010222: call_init (dl-init.c:36)
==13337==    by 0x4010222: _dl_init (dl-init.c:126)
==13337==    by 0x4001309: ??? (in /lib/x86_64-linux-gnu/ld-2.19.so)
==13337== 
==13337== LEAK SUMMARY:
==13337==    definitely lost: 20 bytes in 1 blocks
==13337==    indirectly lost: 0 bytes in 0 blocks
==13337==      possibly lost: 0 bytes in 0 blocks
==13337==    still reachable: 72,704 bytes in 1 blocks
==13337==         suppressed: 0 bytes in 0 blocks
==13337== 
==13337== ERROR SUMMARY: 7 errors from 3 contexts (suppressed: 0 from 0)
==13337== 
==13337== 1 errors in context 1 of 3:
==13337== Invalid free() / delete / delete[] / realloc()
==13337==    at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13337==    by 0x4009B7: main (in /media/areuz/Storage - Linux/1 :: Documents/Programming/2 :: C++ Language/1 :: C++ Codes/Divisibility Check/divisibility)
==13337==  Address 0x5a37c80 is 0 bytes inside a block of size 4 free'd
==13337==    at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13337==    by 0x400A0A: get_divisors(int, int*) (in /media/areuz/Storage - Linux/1 :: Documents/Programming/2 :: C++ Language/1 :: C++ Codes/Divisibility Check/divisibility)
==13337==    by 0x400964: main (in /media/areuz/Storage - Linux/1 :: Documents/Programming/2 :: C++ Language/1 :: C++ Codes/Divisibility Check/divisibility)
==13337== 
==13337== 
==13337== 5 errors in context 2 of 3:
==13337== Invalid read of size 4
==13337==    at 0x400985: main (in /media/areuz/Storage - Linux/1 :: Documents/Programming/2 :: C++ Language/1 :: C++ Codes/Divisibility Check/divisibility)
==13337==  Address 0x5a37c80 is 0 bytes inside a block of size 4 free'd
==13337==    at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13337==    by 0x400A0A: get_divisors(int, int*) (in /media/areuz/Storage - Linux/1 :: Documents/Programming/2 :: C++ Language/1 :: C++ Codes/Divisibility Check/divisibility)
==13337==    by 0x400964: main (in /media/areuz/Storage - Linux/1 :: Documents/Programming/2 :: C++ Language/1 :: C++ Codes/Divisibility Check/divisibility)
==13337== 
==13337== ERROR SUMMARY: 7 errors from 3 contexts (suppressed: 0 from 0)

问题:

get_divisor() 函数中,以下语句重新分配指针:

       num_result = (int*)realloc(num_result, num_count*sizeof(int));

num_result是按值传递的参数,因此您只需更改此局部变量。 main 中的指针保持不变,因此,如果内存移动到另一个地址,您将在从函数返回后立即丢失重新分配的内存。

快速修复:

您可以通过引用传递指针,以便它实现您的预期方法(即原始指针确实在函数中被修改)。 只需更改函数签名/定义:

int get_divisors(int num_input, int *&num_result);  // pass by reference

更好的方法:

首先,你应该真正摆脱 C++ 中的malloc()realloc():它们适用于基本类型,但不尊重更复杂对象(即未构造对象)的对象生命周期。

接下来,你不应该重新发明轮子。 与其管理自己一个可变大小的数组,不如选择向量:

vector<int> vnum_result(1);  // initial size is one.  
vnum_result.resize(num_count);  // change the size 
                                // no worries about freeing.  

当然,通过引用或按值传递的问题仍然存在。

你应该习惯C++容器,不要害怕返回容器(查找返回值优化和复制省略):

#include <iostream>
#include <vector>
std::vector<int> get_divisors(int num_input)
{
    std::vector<int> result;
    for (int loop_1 = 1; loop_1 < num_input; loop_1++) {
        if (num_input % loop_1 == 0) {
            result.push_back(loop_1);
        }
    }
    return result;
}
int main()
{
    int num_input;
    if(std::cin >> num_input) {
        std::vector<int> divisors = get_divisors(num_input);
        // You may consider a ranged base for: for (int divisor : divisors)
        for (std::size_t loop_1 = 0; loop_1 < divisors.size(); loop_1++){
            std::cout << divisors[loop_1] << "n";
        }
    }
}