在哪里为指针及其数据分配内存? [英] where is memory allocated for pointers and their data?

查看:95
本文介绍了在哪里为指针及其数据分配内存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题是我是否有功能

My question is if i have some function

void func1(){
    char * s = "hello";
    char * c;
    int b;
    c = (char *) malloc(15);
    strcpy(c,s);
}

我认为s指针分配在堆栈上,但是"hello"数据存储在程序的数据段中在哪里?至于c和b,它们是单位化的,并且由于'c = some memory address'并且它还没有,这是如何工作的?并且b也没有内容,因此无法将其存储在堆栈中? 然后,当我们使用malloc c在堆上为c分配内存时,现在有了一些内存地址,这个单元化的c变量如何给出堆上该字符串的第一个字节的地址?

I think the s pointer is allocated on the stack but where is the data "hello" stored does that go in the data segment of the program? As for c and b they are unitialized and since 'c = some memory address' and it doesnt have one yet how does that work? and b also has no contents so it cant stored on the stack? Then when we allocate memory for c on the heap with malloc c now has some memory address, how is this unitialized c variable given the address of the first byte for that string on the heap?

推荐答案

让我们将答案分为同一观点的两种观点,因为这些标准只会使对该主题的理解复杂化,但无论如何它们都是标准:).

Let's divide this answer in two points of view of the same stuff, because the standards only complicate understanding of this topic, but they're standards anyway :).

两个部分共同的主题

void func1() {
    char *s = "hello";
    char *c;
    int b;

    c = (char*)malloc(15);
    strcpy(c, s);
}

第一部分:从标准角度看

根据标准,有一个有用的概念称为自动变量持续时间,其中,变量的空间在输入给定范围(具有统一值,又名:垃圾!)后自动保留.可以在这样的范围内设置/访问或不设置,并且可以释放该空间以供将来使用. 注意:在C ++中,这还涉及对象的构造和破坏.

Part I: From a standardese point of view

According to the standards, there's this useful concept known as automatic variable duration, in which a variable's space is reserved automatically upon entering a given scope (with unitialized values, a.k.a: garbage!), it may be set/accessed or not during such a scope, and such a space is freed for future use. Note: In C++, this also involves construction and destruction of objects.

因此,在您的示例中,您具有三个自动变量:

So, in your example, you have three automatic variables:

  • char *s,它会初始化为"hello"的地址.
  • char *c,它将保留垃圾,直到被以后的分配初始化为止.
  • int b,它在整个生命周期中都保存着垃圾.
  • char *s, which gets initialized to whatever the address of "hello" happens to be.
  • char *c, which holds garbage until it's initialized by a later assignment.
  • int b, which holds garbage all of its lifetime.

顺便说一句,标准未指定存储与功能的工作方式.

BTW, how storage works with functions is unspecified by the standards.

在任何体面的计算机体系结构上,您都可以找到称为 stack 的数据结构.堆栈的目的是保留可由自动变量使用和回收的空间,以及一些递归/函数调用所需的某些东西的空间,并且如果编译器可以用作存放临时值(出于优化目的)的地方决定这样做.

On any decent computer architecture you will find a data structure known as the stack. The stack's purpose is to hold space that can be used and recycled by automatic variables, as well as some space for some stuff needed for recursion/function calling, and can serve as a place to hold temporary values (for optimization purposes) if the compiler decides to.

堆栈以PUSH/POP的方式工作,即堆栈向下增长 .让我更好地解释一下.想象这样一个空堆栈:

The stack works in a PUSH/POP fashion, that is, the stack grows downwards. Let my explain it a little better. Imagine an empty stack like this:

[Top of the Stack]
[Bottom of the Stack]

例如,如果您将PUSHint的值设置为5,则会得到:

If you, for example, PUSH an int of value 5, you get:

[Top of the Stack]
5
[Bottom of the Stack]

然后,如果您PUSH -2:

[Top of the Stack]
5
-2
[Bottom of the Stack]

然后,如果您按POP,则检索-2,并且堆栈看起来与-2PUSH之前一样.

And, if you POP, you retrieve -2, and the stack looks as before -2 was PUSHed.

堆栈的底部是一个障碍物,可以向上和向下移动.在大多数架构上,堆栈的底部是由称为处理器寄存器记录的.堆栈指针.将其视为unsigned char*.您可以减少它,增加它,对它做指针算术,等等.一切目的都是在堆栈的内容上产生黑魔法.

The bottom of the stack is a barrier that can be moved uppon PUSHing and POPing. On most architectures, the bottom of the stack is recorded by a processor register known as the stack pointer. Think of it as a unsigned char*. You can decrease it, increase it, do pointer arithmetic on it, etcetera. Everything with the sole purpose to do black magic on the stack's contents.

通过减小(记住,它向下增长)来完成栈中自动变量的保留(空间),并通过增加来实现释放它们.基于此,以前的理论PUSH -2在伪汇编中是类似这样的缩写:

Reserving (space for) automatic variables in the stack is done by decreasing it (remember, it grows downwards), and releasing them is done by increasing it. Basing us on this, the previous theoretical PUSH -2 is shorthand to something like this in pseudo-assembly:

SUB %SP, $4    # Subtract sizeof(int) from the stack pointer
MOV $-2, (%SP) # Copy the value `-2` to the address pointed by the stack pointer

POP whereToPop仅仅是反函数

MOV (%SP), whereToPop # Get the value
ADD %SP, $4           # Free the space

现在,编译func1()可能会产生以下伪程序集(注意:您应该完全理解):

Now, compiling func1() may yield the following pseudo-assembly (Note: you are not expected to understand this at its fullest):

.rodata # Read-only data goes here!
.STR0 = "hello" # The string literal goes here

.text # Code goes here!
func1:
    SUB %SP, $12     # sizeof(char*) + sizeof(char*) + sizeof(int)
    LEA .STR0, (%SP) # Copy the address (LEA, load effective address) of `.STR0` (the string literal) into the first 4-byte space in the stack (a.k.a `char *s`)
    PUSH $15         # Pass argument to `malloc()` (note: arguments are pushed last to first)
    CALL malloc
    ADD %SP, 4       # The caller cleans up the stack/pops arguments
    MOV %RV, 4(%SP)  # Move the return value of `malloc()` (%RV) to the second 4-byte variable allocated (`4(%SP)`, a.k.a `char *c`)
    PUSH (%SP)       # Second argument to `strcpy()`
    PUSH 4(%SP)      # First argument to `strcpy()`
    CALL strcpy
    RET              # Return with no value

我希望这能给您带来启发!

I hope this has led some light on you!

这篇关于在哪里为指针及其数据分配内存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆