一道内存分配的面试题_js

一道内存分配的面试题_nginx_02

我之前写的文章有很完整说过这部分

C语言,函数不可返回指向栈内存的指针

C 语言内存分配

堆和栈的区别(转过无数次的文章)

看完上面的文章,我觉得你至少对C语言程序变量内存有一个概念了解了。

然后看下这几张图

一道内存分配的面试题_js_03

一道内存分配的面试题_javascript_04

一道内存分配的面试题_nginx_05

我们想知道一个程序栈的起始地址,我们只需要写个测试程序可以了。

#include "stdio.h"
#include "stdlib.h"

int main(void)
{
int a = 3;
int *p = (int *)malloc(sizeof(int));

printf("%p\n",&a);
printf("%p\n",&p);
printf("%p\n",p);
return 0;
}

我们期望是这样的

一道内存分配的面试题_html_06

实际运行是这样的,跟我们预期符合

0x7ffc3f47e1cc
0x7ffc3f47e1d0
0x562bf8677260

当然,也可以通过一些Linux 命令来查看这些信息

如果还有其他命令大家可以补充

size
nm
objdump

size 可以看到每个内存段的大小

weiqifa@bsp-ubuntu1804:~/c$ gcc neicunfenpei.c &&size ./a.out
text data bss dec hex filename
1802 616 8 2426 97a ./a.out
weiqifa@bsp-ubuntu1804:~/c$

nm 可以看到更多的信息,包括里面的地址,还有标识符的区域,想看详细的可以看看man nm。

#include "stdio.h"
#include "stdlib.h"

int gint = 1;

int main(void)
{
char * pch = "1231231";
int a = 3;
int *p = (int *)malloc(sizeof(int));

printf("%p\n",&a);
printf("%p\n",&p);
printf("%p\n",p);
return 0;
}

查看输出

weiqifa@bsp-ubuntu1804:~/c$ gcc neicunfenpei.c &&size ./a.out
text data bss dec hex filename
1826 620 4 2450 992 ./a.out
weiqifa@bsp-ubuntu1804:~/c$ gcc neicunfenpei.c &&nm ./a.out
0000000000201014 B __bss_start
0000000000201014 b completed.7698
w __cxa_finalize@@GLIBC_2.2.5
0000000000201000 D __data_start
0000000000201000 W data_start
0000000000000620 t deregister_tm_clones
00000000000006b0 t __do_global_dtors_aux
0000000000200db0 t __do_global_dtors_aux_fini_array_entry
0000000000201008 D __dso_handle
0000000000200db8 d _DYNAMIC
0000000000201014 D _edata
0000000000201018 B _end
0000000000000814 T _fini
00000000000006f0 t frame_dummy
0000000000200da8 t __frame_dummy_init_array_entry
0000000000000974 r __FRAME_END__
0000000000201010 D gint
0000000000200fa8 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000000000000830 r __GNU_EH_FRAME_HDR
0000000000000580 T _init
0000000000200db0 t __init_array_end
0000000000200da8 t __init_array_start
0000000000000820 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
0000000000000810 T __libc_csu_fini
00000000000007a0 T __libc_csu_init
U __libc_start_main@@GLIBC_2.2.5
00000000000006fa T main
U malloc@@GLIBC_2.2.5
U printf@@GLIBC_2.2.5
0000000000000660 t register_tm_clones
U __stack_chk_fail@@GLIBC_2.4
00000000000005f0 T _start
0000000000201018 D __TMC_END__

ojbdump 大家可以自己去看看,参数比较多

来看看我们前面说的题目

#include "stdio.h"

char * test_function(int n)
{
int a = 3;
char *p1 = "123";
char p2[] = "456";
printf("%p %p %p\n",&a,p1,p2);
if(n == 0)
return p1;
return (char *)p2;
}

int main(void)
{
printf("%s\n",test_function(0));
printf("%s\n",test_function(1));
getchar();
return 0;
}

这个代码在gcc下是编译会出现警告,而且运行后会出现段错误,因为我们访问了一个非法内存。

weiqifa@bsp-ubuntu1804:~/c$ gcc neicunfenpei.c && ./a.out
neicunfenpei.c: In function ‘test_function’:
neicunfenpei.c:11:12: warning: function returns address of local variable [-Wreturn-local-addr]
return (char *)p2;
^~~~~~~~~~
0x7fffe549a724 0x5641eaea1874 0x7fffe549a734
123
0x7fffe549a724 0x5641eaea1874 0x7fffe549a734
Segmentation fault (core dumped)
weiqifa@bsp-ubuntu1804:~/c$

你以为这就完了?

在devC++下,是可以正常运行的

一道内存分配的面试题_js_07

这个dev C++ 让我觉得有点意思

一道内存分配的面试题_js_08

所以在gcc 下,我们修改下代码

#include "stdio.h"

char * pg =NULL;

char * test_function(int n)
{
int a = 3;
char *p1 = "123";
char p2[] = "456";
pg = (char *)p2;
printf("%p %p %p\n",&a,p1,p2);
if(n == 0)
return p1;
return pg;
}

int main(void)
{
printf("%s\n",test_function(0));
printf("%s\n",test_function(1));
getchar();
return 0;
}

再运行

一道内存分配的面试题_linux_09

没有段错误,但是第二次输出为空!

所以,你下次面试遇到,知道怎么回答了吗?

关注公众号,后台回复「​1024​」获取学习资料网盘链接。

欢迎点赞,关注,转发您的每一次鼓励,我都将铭记于心~

一道内存分配的面试题_html_10

嵌入式Linux