代码之家  ›  专栏  ›  技术社区  ›  vansergh

如何为malloc分配的数组释放内存?

  •  0
  • vansergh  · 技术社区  · 1 年前

    我有两种代码变体:

    第一个:

    void PrintMem(const int* memarr,const size_t size) {
        for (size_t index = 0; index < size; ++index) {
            std::cout << '<'<<(index+1)<<"> "s<<*(memarr + index) << std::endl;
        }
    }
    
    void FillMem(int* memarr, const size_t size) {
        srand(time(0));
        for (size_t index = 0; index < size; ++index) {
            *(memarr + index) = rand() % 100;
        }
    }
    
    int main() {
        const int size_iter = 10000000;
        int n = 30;
        int* ptr = nullptr;
        int size = size_iter;
        for (int i = 1; i <= n; ++i) {
            size = size_iter * i;
            if (i == 1) {
                ptr = (int*)malloc(size * sizeof(int));
            }
            else {
                ptr = (int*)realloc(ptr, size * sizeof(int));    
            }
            if (ptr == nullptr) {
                printf("memory allocation error\n");
                break;
            }
            std::cout << '[' << i << ']';
            printf(" address: %p", (void*)ptr);
            std::cout << ", size: "s << size;
            std::cout << " *********************" << std::endl;
            FillMem(ptr, size);
            //PrintMem(ptr, size);
    
        }
        if (ptr != nullptr) {
            free(ptr);
        }
    }
    

    第二:

    void PrintMem(const int* memarr,const size_t size) {
        for (size_t index = 0; index < size; ++index) {
            std::cout << '<'<<(index+1)<<"> "s<<*(memarr + index) << std::endl;
        }
    }
    
    void FillMem(int* memarr, const size_t size) {
        srand(time(0));
        for (size_t index = 0; index < size; ++index) {
            *(memarr + index) = rand() % 100;
        }
    }
    
    int main() {
        const int size_iter = 10000000;
        int n = 30;
        int* ptr = nullptr;
        int size = size_iter;
        for (int i = 1; i <= n; ++i) {
            size = size_iter * i;
            int* new_ptr = nullptr;
            if (i == 1) {
                new_ptr = (int*)malloc(size * sizeof(int));
            }
            else {
                new_ptr = (int*)realloc(ptr, size * sizeof(int));    
            }
            if (new_ptr == nullptr) {
                printf("memory allocation error\n");
                break;
            }
            ptr = new_ptr;
            std::cout << '[' << i << ']';
            printf(" address: %p", (void*)ptr);
            std::cout << ", size: "s << size;
            std::cout << " *********************" << std::endl;
            FillMem(ptr, size);
            //PrintMem(ptr, size);
    
        }
        if (ptr != nullptr) {
            free(ptr);
        }
    }
    

    释放阵列内存的正确方法是什么?

    if (ptr != nullptr) {
        free(ptr);
    }
    

    if (ptr != nullptr) {
        for (int i = 0; i < size; ++i) {
            free((ptr + i));
       }
       free(ptr);
    }
    

    我尝试了两种变体。

    具有的第二个变体 int* new_ptr 我认为会更好,因为它至少会保持之前的内存大小调整迭代。

    我只需要知道如何优化它,如果只免费是正确的 ptr 还是需要释放每个内存块?

    1 回复  |  直到 1 年前
        1
  •  5
  •   Remy Lebeau    1 年前

    你在打电话 malloc() 仅一次创建数组,并且调用 realloc() 多次重新分配阵列。只有1个数组,因此需要调用 free() 只有一次可以释放该数组。不要尝试 自由的 单个元素,因为它们不是 malloc ”单独地说。一 自由的 成功的 malloc() / realloc() .

    此外,您不需要检查 nullptr 打电话之前 自由的 ,因为它已经在内部处理了。

    此外,如果 realloc() 失败,原始数组未受影响,但您正在覆盖您的 ptr 变量,因此将泄漏现有数组。你需要检查 realloc() 失败 之前 你重新分配了 ptr 变量

    顺便说一句,剩下的代码还有其他一些小毛病:

    • 你应该使用 memarr[index] 而不是 *(memarr + index) .

    • 不要打电话 srand() 多次。打一次电话 main() .

    • "> "s 应该只是 "> " ,没有必要强迫它 std::string 只是为了打印它,作为 operator<< 可以很好地处理字符串文字(在其他一些打印中很明显)。

    • 你不应该混在一起 printf() 具有 std::cout 。坚持其中一个。

    请尝试类似的操作:

    void PrintMem(const int* memarr, const size_t size) {
        for (size_t index = 0; index < size; ++index) {
            std::cout << '<' << (index+1) << "> " << memarr[index] << '\n';
        }
    }
    
    void FillMem(int* memarr, const size_t size) {
        for (size_t index = 0; index < size; ++index) {
            memarr[index] = rand() % 100;
        }
    }
    
    int main() {
        srand(time(0));
        const int size_iter = 10000000;
        int n = 30;
        int* ptr = nullptr;
        for (int i = 1; i <= n; ++i) {
            int size = size_iter * i;
            if (i == 1) {
                ptr = static_cast<int*>(malloc(size * sizeof(int)));
                if (ptr == nullptr) {
                    std::cerr << "memory allocation error\n";
                    break;
                }
            }
            else {
                int *new_ptr = static_cast<int*>(realloc(ptr, size * sizeof(int)));
                if (new_ptr == nullptr) {
                    std::cerr << "memory reallocation error\n";
                    break;
                }
                ptr = new_ptr;
            }
            std::cout << '[' << i << ']';
            std::cout << " address: " << static_cast<void*>(ptr);
            std::cout << ", size: " << size;
            std::cout << " *********************\n";
            FillMem(ptr, size);
            //PrintMem(ptr, size);
        }
        free(ptr);
    }
    

    话虽如此,你真的不应该使用 malloc / realloc() 在C++中。使用 std::vector 相反,让它为您处理内存,例如:

    #include <vector>
    
    void PrintMem(const std::vector<int> &arr) {
        for (size_t index = 0; index < arr.size(); ++index) {
            std::cout << '<' << (index+1) << "> " << memarr[index] << '\n';
        }
    }
    
    void FillMem(std::vector<int> &arr) {
        for (size_t index = 0; index < arr.size(); ++index) {
            memarr[index] = rand() % 100;
        }
    }
    
    int main() {
        srand(time(0));
        const int size_iter = 10000000;
        int n = 30;
        std::vector<int> arr;
        for (int i = 1; i <= n; ++i) {
            int size = size_iter * i;
            arr.resize(size);
            std::cout << '[' << i << ']';
            std::cout << " address: " << static_cast<void*>(arr.data());
            std::cout << ", size: " << size;
            std::cout << " *********************\n";
            FillMem(arr);
            //PrintMem(arr);
        }
    }
    

    您还应该考虑使用 C++-style random-number generator 来自 <random> 库,而不是使用C样式 rand() .

    此外,考虑使用 range-for loops standard algorithms 喜欢 std::for_each() , std::generate()

    简而言之,尽可能避免在C++中使用C语言。C和C++可能曾经有过共同的遗产,但它们已经进化成了截然不同的语言。