前不久在写代码的过程中,遇到以下情景:在一个函数中,需要使用两个比较大的结构(均达到8-9K,假设为struct a和struct b),因为是在嵌入式平台上,栈的大小在一开始就固定了,如果直接将这两个结构定义为局部变量,则会造成栈溢出而导致设备crash。
当然,解决这个问题的办法很简单,其中一种就是将局部变量改成动态内存分配。
这样,在任何检查失败的时候,都只需要释放一次内存即可。但随即就想到,如果以后在添加了新的结构进来以后,在计算buf_max_len的时候,岂不是很麻烦,假如有4个,5个甚至更多结构存在的时候,那计算不是更复杂,于是,想到了联合。
这样,以后要是再有新的结构添加进来,只需要在union中新添加一个成员就可以了,然后添加使用新结构的代码即可,其他的事就交给编译器去做吧。当然,缺点也是显而易见地,就是,如果这几个结构不独立的话,也就是会存在交叉使用或同时使用的情况,这招便不管用了。
当然,解决这个问题的办法很简单,其中一种就是将局部变量改成动态内存分配。
因为在函数的处理过程中,会有很多检查,任何一项检查失败,都会直接返回,而不进行后续处理。考虑到尽量少地进行内存分配与释放,以及在同一个函数中,如果分配内存的次数太多,容易造成错误返回的时候,漏释放某些内存,并且由于struct a与struct b这两个结构并不会同时使用,也就是这两个结构的使用相对来说比较独立,于是想到以下办法来复用内存:
.....
struct a *a;
struct b *b;
void *buf;
int buf_max_len;
buf_max_len = sizeof(struct a) > sizeof(struct b) ? sizeof(a) : sizeof(b);
buf = malloc(buf_max_len);
....
a = (struct a*)buf;
/* use a */
....
b = (struct b*)buf;
/* use b*/
...
free(buf);
这样,在任何检查失败的时候,都只需要释放一次内存即可。但随即就想到,如果以后在添加了新的结构进来以后,在计算buf_max_len的时候,岂不是很麻烦,假如有4个,5个甚至更多结构存在的时候,那计算不是更复杂,于是,想到了联合。
....
union union_buf
{
struct a a;
struct b b;
};
union union_buf *buf;
buf = (union union_buf *)malloc(sizeof(union union_buf));
这样,以后要是再有新的结构添加进来,只需要在union中新添加一个成员就可以了,然后添加使用新结构的代码即可,其他的事就交给编译器去做吧。当然,缺点也是显而易见地,就是,如果这几个结构不独立的话,也就是会存在交叉使用或同时使用的情况,这招便不管用了。