跟我一起学习C(内存篇)

上一小节[url=http://beck5859509.iteye.com/blog/2176678]跟我一起学习C(指针篇1)[/url]介绍了指针的基本用法及原理,这章主要介绍C对内存分配的管理。写到这里大家自然会联想到JVM运行时的内存分配,C程序会不会也像JAVA一样类似的处理方式呢?

[color=red][b]JAVA内存管理[/b][/color]

每个JVM程序在启动时根据脚本参数设置内存大小。主要设置堆大小(-Xmx、-Xms设置)、非堆大小(-PermSize、-MaxPermSize),以及内存回收策略(并行UseParallelGC、并发CMS)。

以并行回收为例:
程序中new出来的对象存放在堆区。jconsole下截图
[img]http://dl2.iteye.com/upload/attachment/0105/4633/65b61b43-7438-3db7-87d3-ac8c1343d950.png[/img]

静态数据、字符串常量、class方法等存放在非堆区。
[img]http://dl2.iteye.com/upload/attachment/0105/4641/f06ae00a-6a59-3efa-9059-51d8dd6d8490.png[/img]

以上只是JVM存放数据的物理图,而实际程序运行时数据区涉及到(堆、栈、方法区、程序计数器),这些不在本章中介绍,但它们的数据就是存放在以上两个图中的。
可见JAVA的内存是事先指定好的,如果我们程序中产生的对象不断增加,而GC又回收不了,达到或接近Xmx值时就会报Outofmemory。

[color=red][b]C内存管理[/b][/color]

C的处理方式和JAVA类似么?我们先不急着回答这个问题。来看看编译链接出来的目标文件格式。比如hello.c编译完成以后生成hello,来看一下其内部结构。
[img]http://dl2.iteye.com/upload/attachment/0105/4671/f4203714-921b-3639-b163-df96ff0ecefd.png[/img]
目标文件的大小为7944个字节,而源文件只有320字节。再看第二个红圈中的几个内容及对应解释:

[color=red]text(代码区)[/color]:代码段由各个函数产生,函数的每一个语句将最终经过编绎和汇编生成二进制机器代码。

[color=red]data(数据区)[/color]:程序中明确被初始化的全局变量、静态变量(包括全局静态变量和局部静态变量)和常量数据(如字符串常量)。

[color=red]bss(未初始化数据区)[/color]:存放的是全局未初始化变量(包括静态和全局)

dec(十进制大小):以上几部份内容的10进制之和
hex(十六进制大小):以上几部份内容的16进制之和

由此可见上图中运行时的内存是没有分配的,包括栈和堆的数据。栈数据主要是方法内的私有变量、方法参数、临时数据等。方法运行完后自动释放空间,而堆是由程序动态分配的大小,可动态扩张或缩减([color=red]可以理解成java中new出来的对象,既然new一个对象,至少得知道这个对象要占多大空间,所以先分配空间,然后再往空间中设值,比如一个Person(包括姓名,身份证号)的结构体,就先开辟一个空间,这才可以装下姓名和身份证号[/size][/color]),具体C中就表现为操作malloc和free函数。

使用malloc和free的例子。

void mallocTest(char *q, int size){
q = (char *)malloc(size);
//往新申请的空间中设置字符串
strcpy(q, "hello world!!!");
printf("%s\n", q);

}

int main() {
char *ptr = NULL;
mallocTest(ptr, 128);
free(ptr);
return 0;
}


虽然上面的程序运行没问题,但是内存泄露了,free(p)实际上是free(null),在mallocTest方法中申请的空间没有释放掉。其实这和传参是有关系的。mallocTest方法中指针本身的地址和ptr的本身地址是不一样的(说白了不是同一个变量,只是指针的值都指向null,这个地方和JAVA的传参一样,都是值传递;地址传递只是指针的值是一样的,而形参指针和实参指针本身的地址,实际是两个不同变量),q在mallocTest方法中最后是指向了新分配的空间。如下测试

void mallocTest(char *q, int size){
printf("pointer2 ---->%p\n",&q);
q = (char *)malloc(size);
strcpy(q, "hello world!!");
printf("%s\n", q);
}

int main() {
char *ptr = NULL;
printf("pointer1 ---->%p\n",&ptr);
mallocTest(ptr, 128);
free(ptr);
return 0;
}

[img]http://dl2.iteye.com/upload/attachment/0105/4879/30d1150a-e364-3d72-8204-8db104541abd.png[/img]
正确的写法
方法1:把函数中的指针返回出来,再赋值给主函数的指针。

char * mallocTest(char *q, int size){
q = (char *)malloc(size);
strcpy(q, "hello world!!");
printf("%s\n", q);
return q;
}

int main() {
char *ptr = NULL;
ptr = mallocTest(ptr, 128);
free(ptr);
return 0;
}


方法2:使用二级指针,在mallocTest中改变一级指针的值,一级指针指向新申请的空间地址。

void mallocTest(char **q, int size){
*q = (char *)malloc(size);
strcpy(*q, "hello world!");
printf("%s\n", *q);
}

int main() {
char *ptr = NULL;
mallocTest(&ptr, 128);
free(ptr);
return 0;
}


A机器防火墙设置禁止访问地址B
1、/etc/sysconfig/iptables 中添加
-A INPUT -s 10.1.1.53/32 -j DROP
-A INPUT -s 10.0.0.0/8 -j ACCEPT

2、/etc/init.d/iptables reload 执行生效

3、service iptables stop
service iptables status
service iptables start
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值