C 编译时和运行时内存分配之间的时间差

C 编译时和运行时内存分配之间的时间差,c,algorithm,ram,C,Algorithm,Ram,我在某个地方读到分配k个字的内存所用的时间是O(k),我想知道这个时间对于运行时和编译时内存分配是相同的,这意味着我想知道int A[100]和int*A=(int*)malloc(sizeof(int)*100)需要相同或不同的时间动态分配内存可能需要O(k)个时间。它取决于分配器(malloc)或它调用的函数之一是否在返回之前初始化内存。例如,如果malloc调用WindowsLocalAlloc函数从操作系统获取内存,它可以传递LMEM_zeronit标志将所有字节初始化为0 出于安全原因

我在某个地方读到分配k个字的内存所用的时间是O(k),我想知道这个时间对于运行时和编译时内存分配是相同的,这意味着我想知道int A[100]
int*A=(int*)malloc(sizeof(int)*100)需要相同或不同的时间

动态分配内存可能需要O(k)个时间。它取决于分配器(
malloc
)或它调用的函数之一是否在返回之前初始化内存。例如,如果
malloc
调用Windows
LocalAlloc
函数从操作系统获取内存,它可以传递
LMEM_zeronit
标志将所有字节初始化为0

出于安全原因,某些操作系统内存分配器会自动将初始化内存归零。
malloc
的一些实现将使用诸如0xDEADBEEF之类的已知模式初始化内存,特别是在调试模式下。这样,如果您读取一个内核转储,您可以看到您的程序是否正在访问已分配但未由程序初始化的内存


所以你没有问的明确问题的答案是,是的,有可能,甚至可能,动态内存分配k字节需要O(k)个时间。

从算法上讲,静态分配是O(1),动态分配取决于特定的
malloc
算法。从技术上讲,静态分配可能会影响二进制加载/进程生成时间。但根本不是线性的,没有“编译时分配”这样的东西。分配通常是程序和操作系统之间的动态交互。可由编译器自动放置的存储(静态和自动)记录在可执行文件中,并且在代码运行之前由OS加载程序执行分配。这里有关于您的存储是初始化的还是未初始化的,以及它是常量还是可变的详细信息。因此,简单地说,静态分配(
inta[100]
)是在调用
main()
之前完成的,如果没有足够的内存(比如
inta[9999999999]
),它将不会启动。如果从开始算起时间,那么是的,它“更快”,因为它可能会启动,动态分配可能不需要时间,或者根本不会启动,而动态分配在运行时会占用一些CPU周期。IMO,$k$字的分配从来都不是$O(k)$,我想知道这是怎么回事。编译时分配实际上是免费的,因为它是在加载时执行的,即在执行开始之前。相反,运行时分配需要一段未指定的时间。为了安全起见,内存必须在交给进程之前由操作系统初始化,这也适用于进程映像,包括bss段(即静态变量)。如果对malloc的调用导致对操作系统的请求,那么它将涉及初始化。但在许多应用程序中,对malloc的许多调用都满足于先前分配和释放的内存。这样,除了调试之外,初始化是不必要的,而且通常不会完成。@rici:看起来Windows在一个进程释放内存时会在一个单独的线程上清除内存。看见如果是这样的话,那么调用操作系统来分配内存将不会产生初始化成本。这很有趣,也很聪明,但它只会延迟成本。在单独的线程中执行只会使簿记复杂化;它仍然会发生,并且仍然要向分配收费。但我相信它改善了用户体验。