为什么系统不能正确释放C和Rust程序的内存?但是C++程序好像没有问题

问题描述 投票:0回答:1
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *thread_function(void *arg) {
    char **records = malloc(1000000 * sizeof(char *));
    if (records == NULL) {
        perror("Memory allocation failed");
        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < 1000000; ++i) {
        records[i] = malloc(16);
        if (records[i] == NULL) {
            perror("Memory allocation failed");
            exit(EXIT_FAILURE);
        }
        sprintf(records[i], "%d", i);
    }

    printf("done\n");

    for (int i = 0; i < 1000000; ++i) {
        free(records[i]);
    }
    free(records);

    pthread_exit(NULL);
}

int main() {
    pthread_t threads[400];

    for (int i = 0; i < 400; ++i) {
        if (pthread_create(&threads[i], NULL, thread_function, NULL) != 0) {
            perror("Thread creation failed");
            exit(EXIT_FAILURE);
        }
    }

    for (int i = 0; i < 400; ++i) {
        pthread_join(threads[i], NULL);
    }

    while (1) {
      sched_yield();
    }

    return 0;
}

fn main() {
    for _ in 0..400 {
        std::thread::spawn(|| {
            let mut records: Box<Vec<String>> = Box::default();
            for i in 0..1_000_000 {
                let record = i.to_string();
                records.push(record);
            }
            println!("done");
        });
    }

    loop {
        std::thread::yield_now();
    }
}
#include <iostream>
#include <thread>
#include <vector>

int main() {
  for (int i = 0; i < 1600; ++i) {
    std::thread([=]() {
      std::vector<std::string> records;
      for (int i = 0; i < 1000000; ++i) {
        std::string record = std::to_string(i);
        records.push_back(record);
      }
      std::cout << "done" << std::endl;
    }).detach();
  }

  while (true) {
    std::this_thread::yield();
  }

  return 0;
}

我使用

top
(以及 Mac 上的内置监视器)来检查程序的内存使用情况。当 C 和 Rust 程序中的逻辑到达具有无限循环的代码块时,内存没有被正确回收,并且仍然有大量内存在使用,通常为数百兆字节。然而,对于 C++ 程序,内存使用量仍然很低,通常只有几兆字节。我已经研究这个问题几天了,我的猜测包括内存碎片或可能过度内存释放的可能性。它还可能与分配器缓存有关(考虑到调用系统接口来分配内存会产生一些开销)。然而,我还没有找到令人信服的答案。鉴于我在系统编程方面的经验有限,是否有一些我可能缺乏的关键知识?你能为我解释一下吗?仅当线程计数足够高(理想情况下,略低于被终止的阈值)时,才会触发不正确的内存释放。这对我来说是另一个重要的难题。如果线程数较低,则不会出现此问题。如果您尝试在本地复制此内容,建议尝试调整线程数。

c++ c rust memory memory-leaks
1个回答
0
投票

现代 C++ 标准库实现通常使用小型字符串优化,其中字符存储在字符串结构中,直到字符串达到一定大小(例如 64 位系统上的 20 个以上字符)。由于所有字符串都很小,因此它们从不使用单独的堆分配。因此,每个线程仅将堆上的向量内存关联到单个块中(尽管随着向量的增长,将临时创建第二个内存)。

Rust 似乎没有任何 SSO,因此除了容器的分配之外,您的 rust 和 c 实现还为每个字符串进行单独的堆分配。这会导致内存使用量增加,堆碎片也会增加,从而增加操作系统中的明显内存使用量。

但是,你的程序都没有真正的内存泄漏,如果你无限期地继续运行它们,我想它们都会稳定在一个设定值(假设在任何时候运行的线程数都不会增加)。

© www.soinside.com 2019 - 2024. All rights reserved.