C中的malloc()与内存使用

C中的malloc()与内存使用,c,memory,memory-leaks,memory-management,malloc,C,Memory,Memory Leaks,Memory Management,Malloc,我试着用malloc做一个实验,看看是否可以分配所有可用的内存 我使用了以下简单的程序,有几个问题: int main(void) { char * ptr; int x = 100; while(1) { ptr = (char *) malloc(x++ * sizeof(char) / 2); printf("%p\n",ptr); } return 0; } 1) 为什么当使用较大的数据类型(int,u

我试着用malloc做一个实验,看看是否可以分配所有可用的内存

我使用了以下简单的程序,有几个问题:

int main(void)
{
    char * ptr;
    int x = 100;

    while(1)
    {
        ptr = (char *) malloc(x++ * sizeof(char) / 2);
        printf("%p\n",ptr);
    }

    return 0;
}
1) 为什么当使用较大的数据类型(int,unsigned long long int,long double)时,进程将使用较少的内存,而使用较小的数据类型(int,char)时,它将使用更多的内存

2) 在运行该程序时,当内存达到一定数量(Windows 7上为592mb,64位,8GB RAM交换文件设置为系统管理)后,它将停止分配内存。打印if的输出显示为0,表示为空。为什么在达到此阈值后停止分配内存,而不耗尽系统内存和交换

在下面的帖子中,我发现有人在尝试与我相同的事情,但他们没有看到内存使用方面的差异,但我看到了。

我在Linux内核2.6.32-5-686上尝试了这段代码,得到了类似的结果

任何帮助和解释都将不胜感激


谢谢,

您是如何读取内存使用情况的

1) 使用
char
进行分配时,每次分配的内存比使用
long
分配的内存要少(通常是四分之一,但这取决于机器) 由于程序本身外部的大多数内存使用工具不显示分配的内存,而是实际使用的内存,因此它只显示malloc()本身使用的开销,而不是malloc使用的未使用内存

分配越多,开销越大

如果用每个分配的数据填充malloc'd块,那么应该得到非常不同的结果,以便实际使用内存

2) 我猜你是从同一个工具上读到的?尝试计算实际分配的字节数,它应该显示正确的字节数,而不仅仅是“malloc开销”。

1)这可能是因为内存被分页,并且每个页面都具有相同的大小。如果您的数据无法放入一个页面,并落在两个页面之间,我认为这是移动到下一页的开头,从而在上一页的末尾造成空间损失

2) 阈值较小,因为我认为每个程序都被限制在一定数量的数据上,而这些数据不是您拥有的最大总内存。

1)通常内存是以页面的倍数分配的,因此如果您要求的大小小于一个页面,malloc将至少分配一个页面

2) 这是有道理的,因为在多任务系统中,您不是唯一的用户,您的进程也不是唯一运行的进程,还有许多其他进程共享有限的资源集,包括内存。如果操作系统允许一个进程无限制地分配它所需的所有内存,那么它就不是一个好的操作系统,对吗

最后,在Linux中,内核在您实际开始使用该内存之前不会分配任何物理内存页,因此仅调用malloc实际上不会消耗任何物理内存,当然,除了跟踪分配本身所需的内存之外。不过,我不太清楚Windows

编辑: 下面的示例分配1GB的虚拟内存

#include <stdio.h>
int main(int agrc, char **argv)
{
    void *p = malloc(1024*1024*1024);
    getc(stdin);
}
如果您将malloc更改为calloc,并再次运行top,您将得到

1) 分配内存时,每次分配占用请求内存的空间加上堆帧的大小。参见相关问题


2) 在Windows中,任何单个malloc的大小都限制为_HEAP_MAXREQ。有关更多信息和一些解决方法,请参阅。

使用
long
应该会有更多内存。你试过什么?您要输出的只是内存中存储它的位置,而不是分配的内存。在您的示例中,您分配了50个字节。只是想在其他人之前说,不要强制转换malloc的返回值。哦,嘘!!本地堆和系统堆之间有区别。在Windows中,应用程序不会获得很大的本地堆,因此malloc会更快地耗尽内存。使用VirtualAlloc()从sysetem堆进行分配。然后问题可能会变成小分配的句柄/页面用完,而不是实际内存。里科拉:为什么不呢?!你建议怎么做?试试calloc。或者写入最后分配的字节。我正在使用Windows中的任务管理器查看内存使用情况。你的解释有道理。当我用数据填充malloc'd块时,程序几乎立即崩溃。你对第1点和第2点的解释现在让我更清楚了。但是,当我在Linux下运行代码,然后运行free命令时,可用内存量减少了。@user1216551我不确定,但我认为这可能是与跟踪分配本身有关的一些开销,我用一个例子更新了我的答案。我的代码在运行top时生成以下内容:PR NI VIRT RES SHR S%CPU%MEM TIME+COMMAND 20 0 3071m 427m 328 R 44.3 85.0 0:11.84malloc@user1216551在我看来这很合理,如果malloc必须实际跟踪所有这些分配及其大小,我已经在这里运行了您的代码,我达到了vert/res:10.3g/804m
top -p `pgrep test`
PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
20   0 1027m  328  252 S    0  0.0   0:00.00 test
top -p `pgrep test`
PR   NI VIRT  RES  SHR S %CPU %MEM    TIME+ COMMAND              
20   0  1027m 1.0g 328 S    0  1.3   0:00.08 test