C语言学习笔记04――程序在内存中的分布以及内存越界问题

匿名 (未验证) 提交于 2019-12-03 00:22:01

C语言程序在内存中的分布:


#include <stdio.h>  char bss[1024*1024];  int main() { return 0;}

现在来看看程序的可执行文件大小


定义 char bss[1024*1024]={0};也是这个结果

可以看到 bss的大小并没有1MB 说明未初始化的全局变量不占程序文件的存储空间



#include<stdio.h>  char data[1024*1024]={1};  int main() {return 0;}

运行结果:



char* p = "12345"


如何使用堆内存:


  void *malloc(size_t size);
 void free(void *ptr);

举个例子:

 #include <stdio.h>  #include <stdlib.h>  #include <sys/types.h>  #include <unistd.h>     int main()  {    printf("%d\n",getpid()); //得到进程id    char* p = malloc(sizeof(char)*10);    char str1[7] = "123avbd";    char* str2 = "101";    printf("&p:%p\np:%p\n",&p,p);    printf("str1:%p\nstr2:%p\n",str1,str2);    while(1){}; //死循环不让程序结束    free(p);    return 0;  }

让我们看一下结果:




其他的有关内存的操作函数:

申请适合数组使用的内存,size指的是一次申请多少个字节的内存,nmemb指的是申请多少次size,申请到的内存会被设置为0

 void *calloc(size_t nmemb, size_t size);

调整内存的大小,可以把ptr指向的内存,变大或变小。如果内存被调小,数据不会立即删除,会一直存在,直到被别人覆盖;如果内存调大,如果后面没有被使用,则在原来的基础上调大,如有人使用,会重新开辟一块内存,再把原来的数据复制过去。

  void *realloc(void *ptr, size_t size);

内存操作辅助函数:


  void bzero(void *s, size_t n);
  void *memset(void *s, int c, size_t n);


碎片问题:对于堆来讲,频繁的malloc()势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低,也就是说当如果没有足够大小的空间,malloc()申请内存可能会失败。


虚拟内存:



内存映射:




内存分配:



内存越界:



我们看个例子:

 #include<stdio.h>  #include<string.h>    int main()  {      char str[10]={};      char arr[10]="0123456789";      printf("str:%p\narr:%p\n",str,arr);      puts(str);      puts(arr);      strcpy(str,"abcdef123456");      puts(str);      puts(arr);      printf("len=%d\n",strlen(str));      printf("size=%d\n",sizeof(str)/sizeof(str[0]));      return 0; }

但是这串字符串的长度已经大于str定义的长度10了,可是编译结果却没有报错 看下编译结果:



这是为什么呢?

内存越界访问造成的后果非常严重,是程序稳定性的致命威胁之一。更麻烦的是,它造成的后果是随机的,表现出来的症状和时机也是随机的,让BUG的现象和本质看似没有什么联系,这给BUG的定位带来极大的困难。

对于内存越界,比较保险的方法还是在编程时就小心,特别是对于外部传入的参数要仔细检查。





易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!