为什么没有分配原始数据类型的内存?

时间:2014-05-18 20:24:48

标签: objective-c cocoa memory memory-management primitive-types

原始数据类型(如char,bool和int)有一些内存。假设char,它有1个字节的内存。当我们在代码中使用char变量时,变量必须要求1个字节的内存。在这种情况下,我们为什么不分配内存。因为我们从不为它分配内存,它如何使用内存,即。在这种情况下,CPU是否为它分配内存。我也在某处读取原始数据类型放在堆栈上并在完成工作时将其删除。什么样的堆栈?在这种情况下,堆栈是如何形成的?

2 个答案:

答案 0 :(得分:5)

当我们创建NSString *变量时,我们也不会为此分配内存。

我们只在调用alloc时分配内存,可以直接由我们调用,也可以在我们调用的方法内调用。

我们已经分配的内存堆中存在NSString对象,但是NSString *变量(它是指向NSString对象的指针)存在于堆栈的内存中我们没有分配。

例如,给出这两个变量:

NSString *stringOne;
NSString *stringTwo;

到目前为止,它们都没有在堆上分配任何内存,尽管它们确实存在于内存中,与内存中存在charBOOLint的方式完全相同。

NSString *stringOne = [[NSString alloc] initWithString:@"Hello world"];
NSString *stringTwo = stringOne;

现在发生了什么?我们在堆上为NSString对象分配了一些内存。然后,我们初始化此内存以表示字符串“Hello world”,然后返回指向此对象的指针并将其分配给stringOne

接下来,我们只是将指针复制到我们用于stringTwo的堆栈内存中。我们没有在堆上分配任何额外的内存。我们只是让我们的两个字符串变量指向堆上相同的已分配内存。

question and answer jsd linked in the comments对堆栈和堆内存有更多解释,这将解答您的一些问题。

还值得注意的是,许多其他编程语言(如C ++)允许在堆栈上创建对象,在这种情况下,我们不会像堆对象那样分配它们。它们确实存在于内存中,与原始数据类型更相似。

答案 1 :(得分:5)

存在过度简单化的风险,数据有三类内存:1)静态,2)堆栈3)堆。

它们以不同的方式分配。

如果你有

 static char something ;

在函数或

中定义
char something ;

在函数之外,该数据由链接器使用编译器的指令定义并由程序加载器分配。

现有的几乎每个处理器都使用堆栈来支持嵌套数据(例如,函数调用)。堆栈是一个存储器块,存在于每个进程(以及每个处理器模式)。有一个称为堆栈指针的硬件寄存器,用于标识堆栈的当前位置。通常SP从堆栈的高端开始并向下工作。要在堆栈上分配内存,程序会从堆栈指针中减去所需的字节数。要解除分配,它会添加到堆栈指针。分配和解除分配总是在同一端进行。

堆栈上有两个操作。 PUSH意味着把东西放在堆栈上。 POP删除它。大多数处理器都有PUSH和POP

的指令

如果你有

 char something

在一个函数中定义,该内存由程序按照编译器的指示分配,通过这样做来调整堆栈指针(我现在忽略一个帧指针)

 SUB   BYTESNEEDED, SP

进入该功能并通过执行

释放
ADD BYTESNEEDED, SP
离开功能前

。在执行函数期间,局部变量与堆栈指针处于偏移状态。

这通常通过使用第二个寄存器来完成,通常称为帧指针。一个函数通常在开始时做这样的事情

PUSH  FP       ; Save the old Frame Point 
MOV   SP  FP   ; Save the stack pointer
SUB   BYTESNEEDED, SP

最后该函数执行类似

的操作

MOV FP,SP;释放该函数分配的所有堆栈    POP FP;恢复旧堆栈指针

使用两个寄存器的原因是可以从堆栈动态分配数据。

这是一个常见的函数(虽然我认为它不是标准的C函数),称为alloca,它是从堆栈分配的malloc的替代

void dosomething (int amount)
{
    char *data = alloca (amount) ;
} 

使用alloca,当函数返回并重置堆栈时,数据会自动释放。

对你的问题,这是一个冗长的回答。是的,当声明一个char时,必须有一个分配。但是,这种分配是在幕后完成的,而不需要您付出任何努力。