最少的钱怎么做网站,网站如何做外链教程视频,郑州做网站找哪家,wordpress段间距写在前头#xff1a; 我不能保证此文中#xff0c;我的观点和理解全是对的#xff0c;这也不是一篇教学贴#xff0c;只是我偶尔突发奇想了几个特殊的场景#xff0c;然后用实验得到结果#xff0c;对结果进行分析#xff0c;遂成此文。所以文中肯定存在错误#xff0c… 写在前头 我不能保证此文中我的观点和理解全是对的这也不是一篇教学贴只是我偶尔突发奇想了几个特殊的场景然后用实验得到结果对结果进行分析遂成此文。所以文中肯定存在错误我也没想到会上首页引来众人围观。 最后欢迎拍砖我觉得错了不要紧改就是了最惨的是不知道自己错在哪。 首先看一下man手册中的定义 void *malloc(size_t size);向系统申请size个Bytes长的连续内存返回一个void类型的指针指向这块儿内存的首地址。这块申请到的内存是不洁的也就是非全0x00内容可以是任意的随机的 如果size的值是0那么返回的指针要么是指向NULL要么是指向一个unique的地址这个地址是可以被free释放的。这里的解释是有问题的例子(8)会证明 void free(void *ptr);释 放ptr指向的内存空间ptr必须是之前调用过malloc,calloc,realloc这三个函数返回的否则如果free(ptr)已经执行过 了而又执行一次那么会导致意外发生undefined behavior occurs.如果ptr指向的是NULL则不会做任何操作。 (1)假设有 1char *p NULL; 2p (char*)malloc(0); 那么p获得的内存块的长度到底是多少能否往里面写入数据答不妨用这段代码来测试 01int main(int argc, char **argv) 02{ 03 char *value NULL; 04 char *ori NULL; 05 value malloc(0); 06 ori value; 07 printf(value[0] is [%c]\n, *value); 08 while(1) { 09 *value a; 10 value; 11 printf(value len [%d]\n, strlen(ori)); 12 } 13} 这段代码结果如下所示Fedora14 01[michaellocalhost mem-test]$ ./a.out 02value[0] is [] 03yydebug:[./mem-test.c]:[34]:value len [1] 04yydebug:[./mem-test.c]:[34]:value len [2] 05yydebug:[./mem-test.c]:[34]:value len [3] 06...省略N行 07yydebug:[./mem-test.c]:[34]:value len [135157] 08yydebug:[./mem-test.c]:[34]:value len [135158] 09yydebug:[./mem-test.c]:[34]:value len [135159] 10Segmentation fault (core dumped) 11[michaellocalhost mem-test]$ 我重新编译、运行了很多次最后打印结果都是135159这 个结果证明了malloc(0)返回的指针指向的是一个非NULL的内存地址处并且该处的值是0x00并且对于该进程不仅该处是可写的而且之后的 135159个Bytes也都是可写的也就是属于这个进程空间。直到最后可能写到别的进程的空间里面去了才被内核发来段错误信号自己结束了。 其实在写该处就已经是内存越界了往后继续写更加是内存越界只是刚好那么巧该处往后的内存块依然是该进程的有效heap区间所以才没有被内核发段错误而往往这种情况是最惨的在实际开发工作中假设哪天真的出个这情况又不会被警告但是却有发现数据被窜改。 (2)假设有 1void *p NULL; 2p malloc(0); 那么稍后p需要用free(p)来释放以避免内存泄漏吗 答不妨用这段代码来测试 01int main(int argc, char **argv) 02{ 03 char *value NULL; 04 05 while(1) { 06 value (char*)malloc(0); 07 printf(value addr [%p]\n, value); 08 } 09 return 0; 10} 结果如下所示 1...幸亏我及时CtrlC停住运行超过几秒电脑就会卡爆了 2value addr [0x87aa5c8] 3value addr [0x87aa5d8] 4value addr [0x87aa5e8]^C 5[michaellocalhost mem-test]$ 从打印看来虽然是调用malloc(0);但是每次指向的地址都不同并且逐渐增大偏移是0x10也就是16个字节。 可以不用while(1)来测试用一个有限的不是很大的值来测试然后用top命令来观察这个进程的资源使用情况可以看出a.out消耗的内存在不断增加所以答案就是malloc(0)申请的内存也要通过free()来释放以避免内存泄漏。 (3)假设有 1char *p NULL; 2free(p); 那么会导致进程退出吗 答案不会free(NULL)相当于啥事儿不干。 (4)假设有 1char *p NULL; 2while(1) { 3 free(p); 4} 那么会导致进程退出吗 答案不会进程永远循环在while(1)里面不会出错退出。 (5)假设有 1void *p NULL; 2p malloc(256); 3free(p); 4free(p); 那么进程会出错退出吗 答案进程会出错退出打印堆栈信息提示 1[michaellocalhost mem-test]$ ./a.out 2*** glibc detected *** ./a.out: double free or corruption (fasttop): 0x09dad008 *** 类似的信息。所以已经free掉的内存除非又申请回来了否则不能再次去free它否则进程会出错。 (6)为什么经常有人说free(p);要和p NULL;一起用以避免“野指针”的出现 答案其实用上面那个例子(5)就能看出如果free超过1次就会出错但是从例子(3)和例子(4)可以看出free(NULL);可以执行任意次 都不会出错。所以一般free(p);之后马上把p指向NULL;从而即使别人再去执行free(p);也不会出现错误。不仅如此通过让p指向 NULL也很好的给别人一个提示你是否对p进行了成功的操作让别人好判断。不妨看看如下的例子 01void foo(char *in)//你做的功能函数 02{ 03 free(in); 04} 05int main(int argc, char **argv) 06{ 07 char *p NULL; 08 p strdup(hello_world); 09 printf(p [%s], len [%d]\n, p, strlen(p)); 10 foo(p); //你同事在调用你的函数 11 12 //感谢a hrefhttp://my.oschina.net/louisluo target_blank relnofollowColoredCotton/a的贡献 13 //由于foo函数的形参是*p所以无法在foo函数内修改实参指针的指向所以这的判断总是true 14 if (NULL ! p) {//他不确定你有木有free()他还很聪明的做了一个判断 15 free(p); 16 p NULL; //他习惯很好free之后指向NULL 17 } 18 return 0; 19} 假设foo函数是你写的你同事在调用foo功能的时候又不确定你是否free了传进去的那块内存于是他就在调用完foo之后加了判断然后执行 free结果他得到的结果是虽然你free了指针p但是这仅仅是告诉内核这块内存我不用了你可以收回了值得注意的是p依然指向这块内存换 句话说也就是指针变量p存的值依然是刚才释放掉的那块内存的首地址。所以你同事的判断得到的结果是true然后又会执行free(p);结果当然和例子 (5)一样了如下所示 1[michaellocalhost mem-test]$ ./a.out 2p [hello_world], len [11] 3*** glibc detected *** ./a.out: double free or corruption (fasttop): 0x09088008 *** 那么“野指针”还可以这样定义指向所有非法地址NULL除外的指针都可以叫野指针。 那么程序应该改成这样较妥 01void foo(char **in)//调用方式应该是传入某个指针的地址 02{ 03 printf( in [%p], in\s address\n, in); 04 printf( in [%p], in\s value\n, in); 05 printf( *in [%p]\n, *in); 06 printf(**in [%c]\n, **in); 07 free(*in); //*in是实参的指针变量p的指向的被分配的内存 08 *in NULL; //使得p指向NULL也就是修改变量p的值 09} 10int main(int argc, char **argv) 11{ 12 char *p NULL; 13 p strdup(hello_world); 14 printf( p [%s], len [%d]\n, p, strlen(p)); 15 printf( p [%p], p\s address\n, p); 16 printf( p [%p], p\s value\n, p); 17 printf( *p [%c], value of addr No.[%p]\n, *p, p); 18 foo(p); //这里应该传入p的地址即p 19 20 //感谢ColoredCotton的贡献 21 //而现在这里的判断就会是false了 22 if (NULL ! p) { //这里的判断就有意义了 23 free(p); 24 p NULL; 25 } 26 else { 27 printf(p is NULL\n); 28 } 29 return 0; 30} 运行一遍看看打印如何 01[michaellocalhost mem-test]$ ./a.out 02 p [hello_world], len [11] 03 p [0xbf94014c], ps address 04 p [0x9964008], ps value 05 *p [h], value of addr No.[0x9964008] 06 in [0xbf940130], ins address 07 in [0xbf94014c], ins value 08 *in [0x9964008] 09**in [h] 10p is NULL 11[michaellocalhost mem-test]$ 我想根据打印信息来看没什么需要解释的了。顺便还弄透彻了指针以及函数传参。 (7)刚malloc后马上就free然后一直循环会不会总是申请到同一块内存 答案这不是真的。不信你用这些代码测试一下就知道了 01int main(int argc, char **argv) 02{ 03 char *p NULL; 04 int ra 0; 05 while(1) { 06 ra rand()%1001; //生成一个1-100之间的随机数 07 if (NULL ! (p (char*)malloc(ra))) { 08 printf(p addr [%p], ra [%d]\n, p, ra); 09 } 10 else { 11 return -1; 12 } 13 free(p); 14 } 15 return 0; 16} 看看打印吧 1p addr [0x8bd8008], ra [59] 2p addr [0x8bd8048], ra [78] 3p addr [0x8bd8008], ra [41] 4p addr [0x8bd8038], ra [46] 5p addr [0x8bd8070], ra [82] 6p addr [0x8bd8008], ra [62] 7p addr [0x8bd8008], ra [91] 8p addr [0x8bd8008], ra [24] 为什么不会一样呢这个可以深究一下Linux系统的内存分配方式了这就涉及到内核了。 (8)malloc(0)返回的真的入man手册所说要么是NULL要么是一个unique的pointer 答案不妨看下这段代码 01int main(int argc, char **argv) 02{ 03 char *p NULL; 04 char *p0 NULL; 05 int ra 0; 06 while(1) { 07 ra rand()%1001; 08 if (NULL (p (char*)malloc(ra))) { 09 printf(error occurs\n); 10 } 11 if (NULL ! (p0 malloc(0))) { 12 printf(p0 addr [%p]\n, p0); 13 } 14 free(p); 15 free(p0); 16 } 17 return 0; 18} 打印如下所示 1p0 addr [0x97eb008] #我随便截取了一段打印 2p0 addr [0x97eb008] 3p0 addr [0x97eb008] 4p0 addr [0x97eb040] 5p0 addr [0x97eb040] 6p0 addr [0x97eb040] 所以从打印看来我用Fedora14测试的时候返回的既不是NULL也不是一个唯一的地址我现在也迷惑了man手册中的unique到底应该如何理解。很遗憾man手册说得不太准确。如果你知道为什么请告诉我如果我哪一天弄明白了我会在这里贴出来的。 (9)如果你也和我一样做了这么多的实验你是不是发现malloc得到的地址的值总是大于0x80000000的32bits机器 答案不好意思我也不知道为什么做了好多次不管如何重新编译、运行得到的结果都是大于0x80000000的如果你知道为什么也请告诉我如果我哪一天弄明白了我会在这里贴出来的。转载于:https://www.cnblogs.com/shihao/archive/2013/01/25/2876739.html