我有两种代码变体:

第一:

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或者我是否需要释放每个内存块?

5

  • 1
    malloc(或callocrealloc)返回一个指针;您应该释放该指针。此外,free正确处理空指针,因此您无需测试。


    – 


  • 2
    为什么在 C++ 程序中使用malloc和?您应该使用“动态数组”。freestd::vector


    – 

  • 4
    概括来说:任何时候您觉得需要进行 C 风格的显式转换(类似 C 风格的强制转换(int *) ...),那么您应该将其视为您可能做错了什么的迹象。


    – 

  • 此外,对于任何指针或数组p和索引i,表达式*(p + i)完全等于p[i]使用数组索引语法通常可以使代码一目了然(并且编写起来更少)。


    – 

  • rand() % 100”——哎哟;1) 不要使用rand()2) 不要使用模数来将值缩小到某个范围,这样会破坏平均值,还会使某些数字比其他数字更有可能。我们有是有原因的。您可能想观看此视频:


    – 



最佳答案
1

您仅调用malloc()一次来创建数组,并realloc()多次调用来重新分配数组。只有一个数组,因此您free()只需调用一次即可释放该数组。不要尝试free()单个元素,因为它们不是malloc单独执行的。free()每次成功的 malloc()/执行一次realloc()

另外,您不需要nullptr在调用之前检查free(),因为它已经在内部处理了。

此外,如果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);
}

话虽如此,你真的不应该在 C++ 中使用malloc/ 。而是使用,让它为你处理内存,例如:realloc()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);
    }
}

您还应该考虑使用库中的<random>,而不是使用 C 风格的rand()

另外,考虑使用,和等。

简而言之,尽可能避免在 C++ 中使用 C 主义。C 和 C++ 可能曾经有共同的传统,但它们已经演变成截然不同的语言。