函数返回值为指针的一个陷阱(使用inet_ntoa函数时遇到的问题)
2015-06-01 22:03
483 查看
此函数在socket编程中使用,将32位大端序整型格式IP地址转换为点分十进制格式。成功时返回转换的字符串地址值,失败时返回-1。
使用一段小代码测试
运行结果
修改代码如下
当分别输出时,正确,如果不是,则错误,即第二次调用函数,对第一次调用有影响。
看看函数的返回值,char * 一个函数如何能做到返回一个内存指针,这段内存再什么地方,栈?还是堆?这是一个问题,一般而言是不可以将栈中的地址return出来的,函数调用结束,所分配的栈的生命周期也就结束。
看看这个函数的源代码,看看其是如何实现的。
buffer为静态局部变量
还有一种函数,比如malloc也是返回一个指针地址,但是区别在于,malloc返回的是在堆中开辟的空间,所以在这个空间生命周期结束后要去释放。而用静态局部变量不需要,每次调用包含静态局部变量的函数,在全局区开辟的空间都要覆盖。
其他博主也遇到此问题,如下
http://blog.chinaunix.net/uid-22663647-id-1771824.html
/article/8796441.html
char * inet_ntoa(struct in_addr addr);
使用一段小代码测试
#include <stdio.h> #include <arpa/inet.h> int main(void){ struct in_addr addr1, addr2; char * str1, * str2; addr1.s_addr = htonl(0xc0a80306); addr2.s_addr = htonl(0xc0a80308); str1 = inet_ntoa(addr1); str2 = inet_ntoa(addr2); printf("%#lx -> %s \n", (long)addr1.s_addr, str1); printf("%#lx -> %s \n", (long)addr2.s_addr, str2); return 0; }
运行结果
gff@ubuntu:~/cplusplus/ping$ ./inetntoa 0x603a8c0 -> 192.168.3.8 0x803a8c0 -> 192.168.3.8
修改代码如下
#include <stdio.h> #include <arpa/inet.h> int main(void){ struct in_addr addr1, addr2; char * str1, * str2; addr1.s_addr = htonl(0xc0a80306); addr2.s_addr = htonl(0xc0a80308); str1 = inet_ntoa(addr1); printf("%#lx -> %s \n", (long)addr1.s_addr, str1); str2 = inet_ntoa(addr2); printf("%#lx -> %s \n", (long)addr2.s_addr, str2); printf("printf together\n"); printf("%#lx -> %s \n", (long)addr1.s_addr, str1); printf("%#lx -> %s \n", (long)addr2.s_addr, str2); return 0; }
gff@ubuntu:~/cplusplus/ping$ ./inetntoa 0x603a8c0 -> 192.168.3.6 0x803a8c0 -> 192.168.3.8 printf together 0x603a8c0 -> 192.168.3.8 0x803a8c0 -> 192.168.3.8
当分别输出时,正确,如果不是,则错误,即第二次调用函数,对第一次调用有影响。
看看函数的返回值,char * 一个函数如何能做到返回一个内存指针,这段内存再什么地方,栈?还是堆?这是一个问题,一般而言是不可以将栈中的地址return出来的,函数调用结束,所分配的栈的生命周期也就结束。
看看这个函数的源代码,看看其是如何实现的。
char * inet_ntoa (struct in_addr in) { __libc_once_define (static, once); char *buffer; unsigned char *bytes; /* If we have not yet initialized the buffer do it now. */ __libc_once (once, init); if (static_buf != NULL) buffer = static_buf; else { /* We don't use the static buffer and so we have a key. Use it to get the thread-specific buffer. */ buffer = __libc_getspecific (key); if (buffer == NULL) { /* No buffer allocated so far. */ buffer = malloc (18); if (buffer == NULL) /* No more memory available. We use the static buffer. */ buffer = local_buf; else __libc_setspecific (key, buffer); } } bytes = (unsigned char *) ∈ __snprintf (buffer, 18, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]); return buffer; }
buffer为静态局部变量
还有一种函数,比如malloc也是返回一个指针地址,但是区别在于,malloc返回的是在堆中开辟的空间,所以在这个空间生命周期结束后要去释放。而用静态局部变量不需要,每次调用包含静态局部变量的函数,在全局区开辟的空间都要覆盖。
其他博主也遇到此问题,如下
http://blog.chinaunix.net/uid-22663647-id-1771824.html
/article/8796441.html
相关文章推荐
- 【网络流】最大流最简单的Ford-Fulkerson算法
- 客运综合管理系统项目—售票管理(留票)
- 微商“造梦”破灭只是个时间问题
- SIP的请求/响应事务模型——SIP学习笔记(二)
- 进程、线程小结(1)
- hdu 1576 A/B
- 石子合并问题
- Unity中影响性能的几个因素
- PHP计划任务之关闭浏览器后仍然继续执行的函数
- hdu 1576 A/B
- LTE中的随机接入过程
- 存储过程调存储过程实例
- bzoj 3261: 最大异或和
- cdoj 31 饭卡(card) 01背包
- CC2541蓝牙学习——看门狗
- 第六节:指导原则和最佳实践
- 第二次冲刺计划会议4
- SqlServer 2008 R2定时备份数据库,并且发送邮件通知
- 第四章t2
- Min Stack