struct内部还有struct_C/C++返回内部静态成员的陷阱

在我们用C/C++开发的过程中,总是有一个问题会给我们带来苦恼。这个问题就是函数内和函数外代码需要通过一块内存来交互(比如,函数返回字符串),这个问题困扰和很多开发人员。如果你的内存是在函数内栈上分配的,那么这个内存会随着函数的返回而被弹栈释放,所以,你一定要返回一块函数外部还有效的内存。

这是一个让无数人困扰的问题。如果你一不小心,你就很有可能在这个上面犯错误。当然目前有很多解决方法,如果你熟悉一些标准库的话,你可以看到许多各式各样的解决方法。大体来说有下面几种:

1)在函数内部通过malloc或new在堆上分配内存,然后把这块内存返回(因为在堆上分配的内存是全局可见的)。这样带来的问题就是潜在的内存问题。因为,如果返回出去的内存不释放,那么就是memory Leak。或者是被多次释放,从而造成程序的crash。这两个问题都相当的严重,所以这种设计方法并不推荐。(在一些Windows API中,当你调用了一些API后,你必需也要调用他的某些API来释放这块内存)

2)让用户传入一块他自己的内存地址,而在函数中把要返回的内存放到这块内存中。这是一个目前普遍使用的方式。很多Windows API函数或是标准C函数都需要你传入一个buffer和这个buffer的长度。这种方式对我们来说应该是屡见不鲜了。这种方式的好处就是由函数外部的程序来维护这块内存,比较简显直观。但问题就是在使用上稍许有些麻烦。不过这种方式把犯错误的机率减到了最低。

3)第三种方式显得比较另类,他利用了static的特性,static的栈内存一旦分配,那这块内存不会随着函数的返回而释放,而且,它是全局可见的(只要你有这块内存的地址)。所以,有一些函数使用了static的这个特性,即不用使用堆上的内存,也不需要用户传入一个buffer和其长度。从而,使用得自己的函数长得很漂亮,也很容易使用。

这里,我想对第三个方法进行一些讨论。使用static内存这个方法看似不错,但是它有让你想象不到的陷阱。让我们来用一个实际发生的案例来举一个例子吧。

示例

有过socket编程经验的人一定知道一个函数叫:inet_ntoa,这个函数主要的功能是把一个数字型的IP地址转成字符串,这个函数的定义是这样的(注意它的返回值):

char *inet_ntoa(struct in_addr in);

显然,这个函数不会分配堆上的内存,而他又没有让你传一下字符串的buffer进入,那么他一定使用“返回static char[]”这种方法。在我们继续我们的讨论之前,让我们先了解一下IP地址相关的知识,下面是inet_ntoa这个函数需要传入的参数:(也许你会很奇怪,只有一个member的struct还要放在struct中干什么?这应该是为了程序日后的扩展性的考虑)

struct in_addr {

unsigned long int s_addr;

}

对于IPV4来说,一个IP地址由四个8位的bit组成,其放在s_addr中,高位在后,这是为了方便网络传输。如果你得到的一个s_addr的整型值是:3776385196。那么,打开你的Windows计算器吧,看看它的二进制是什么?让我们从右到左,8位为一组(如下所示)。

11100001 00010111 00010000 10101100

再把每一组转成十进制,于是我们就得到:225 23 16 172, 于是IP地址就是 172.16.23.225。

好了,言归正传。我们有这样一个程序,想记录网络包的源地址和目地地址,于是,我们有如下的代码:

struct in_addr src, des;................ fprintf(fp, "源IP地址/t目的IP地址/n
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值