内存在栈、堆中是怎么排列的?

How is memory arranged in stack, heap?

下面是我编写的用于检查内存分配的示例程序。

Pavan@Pavan-pc:~/working_dir/pavan/C$ cat mem3.c
    #include <stdio.h>
    #include <string.h>
    #include <stdio.h>

    /* This is generated by a template program */

    typedef struct stru_s{
        char str1[4], str2[4], str3[4];
    }stru_t;
    int main(){
        stru_t st;

        char str1[4], str2[4], str3[4];

        char *mstr1, *mstr2, *mstr3, *mstr4, *mstr5;;

        mstr1= (char*)malloc(4);
        mstr2= (char*)malloc(4);
        mstr3= (char*)malloc(4);
        mstr4= (char*)malloc(8);
        mstr5= (char*)malloc(16);

        strcpy(str1, "aaa");
        strcpy(str2, "bbb");
        strcpy(str3, "ccc");
        strcpy(mstr1, "xxx");
        strcpy(mstr2, "yyy");
        strcpy(mstr3, "zzz");

    return 0;
    }

下面是使用gdb检查内存。

Pavan@Pavan-pc:~/working_dir/pavan/C$ gdb mem3
    GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.el6_4.1)
    Copyright (C) 2010 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "x86_64-redhat-linux-gnu".
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>...
    Reading symbols from /home/xkumapu/working_dir/pavan/C/mem3...done.
    (gdb) b 1
    Breakpoint 1 at 0x4005f0: file mem3.c, line 1.
    (gdb) r
    Starting program: /home/xkumapu/working_dir/pavan/C/mem3
    [Thread debugging using libthread_db enabled]

    Breakpoint 1, main () at mem3.c:17
    17          mstr1= (char*)malloc(4);
    Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.192.el6.x86_64
    (gdb) n
    18          mstr2= (char*)malloc(4);
    (gdb) n
    19          mstr3= (char*)malloc(4);
    (gdb) n
    20          mstr4= (char*)malloc(8);
    (gdb) n
    21          mstr5= (char*)malloc(16);
    (gdb) n
    23          strcpy(str1, "aaa");
    (gdb) n
    24          strcpy(str2, "bbb");
    (gdb)
    25          strcpy(str3, "ccc");
    (gdb)
    26          strcpy(mstr1, "xxx");
    (gdb)
    27          strcpy(mstr2, "yyy");
    (gdb)
    28          strcpy(mstr3, "zzz");
    (gdb)
    30      return 0;
    (gdb)
    31      }
    (gdb) x str1
    0x7fffffffe330: 0x00616161
    (gdb) x str2
    0x7fffffffe320: 0x00626262
    (gdb) x str3
    0x7fffffffe310: 0x00636363
    (gdb) x &str3
    0x7fffffffe310: 0x00636363
    (gdb) x &str2
    0x7fffffffe320: 0x00626262
    (gdb) x &str1
    0x7fffffffe330: 0x00616161  <- Aligned to 16 bytes. (from 320 to 330)
    (gdb) x &mstr1
    0x7fffffffe358: 0x00601060
    (gdb) x &mstr2
    0x7fffffffe360: 0x006010a0
    (gdb) x &mstr3
    0x7fffffffe368: 0x006010e0  <- aligned to 40 bytes. (from 0a0 to 0e0)
    (gdb) x &st.str
    There is no member named str.
    (gdb) x &st.str3
    0x7fffffffe348: 0x00400735
    (gdb) x &st.str2
    0x7fffffffe344: 0x00007fff
    (gdb) x &st.str1
    0x7fffffffe340: 0xffffe478  <- Aligned to just 4 bytes.(from 340 to 344)
    (gdb) q
    A debugging session is active.

            Inferior 1 [process 12541] will be killed.

    Quit anyway? (y or n) y

谁能解释一下为什么在结构中采用不同类型的对齐!!并且是MCB在堆中使用了内存!?

str1 中的 0x00616161 根本不是地址,它只是该字符串的内容,即 "aaa"。请注意,'a' 的 ascii 值是 0x61。所以你说这是 17 字节对齐的说法只是对数据的错误解释。

使用 malloc 分配的字符串有一些额外的 space 因为对于每个分配,因为 malloc 需要一些 space 用于它自己的内部管理,即元数据。

最后,您的堆栈变量只是未初始化,因此您正在寻找垃圾。

GCC 使用 16 字节的默认堆栈对齐方式(请参阅 -mpreferred-stack-boundary 选项)这就是为什么您的指针变量(在堆栈上)对齐到 16 字节的原因。

变量st是一个结构,将根据编译器认为最有效的方式进行打包,但通常字节会在不填充的情况下进行打包。您在结构中放置了 4 个 4 字节的数组,因此不需要填充。因此每个条目都是 4 字节 'aligned'。请注意 st 本身仍然以 16 字节为边界开始,即使它的元素不是。

(如果您的结构中混合了多种类型,编译器将填充它们以确保字对齐,但如果您有充分的理由可以使用属性来关闭填充 - 例如定义某种类型的通信堆栈)

在堆上分配内存的方式(即通过 malloc)是系统堆分配策略的函数(c 库和 OS)- 可以使用不同的分配策略,但这是一个大话题(参见:https://en.wikipedia.org/wiki/Heap_(data_structure)