登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

人在旅途

天空没有痕迹,但我已努力的飞过。。。

 
 
 

日志

 
 

数组大小为0的问题  

2010-03-10 21:26:41|  分类: 计算机 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
在linuxforum上看见有人讨论数组大小为0的理解,觉得不错,特摘录下来,以备参考:
Q:数组大小为0应该怎么理解?
比如:
struct page *page[0];
unsigned long private[0] ____cacheline_aligned;

A:一个很好的例子就是
struct unix_address
{
atomic_t refcnt;
int len;
unsigned hash;
struct sockaddr_un name[0];
};

#define UNIX_PATH_MAX 108

struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* pathname */
};

其中name实际上指向unix_address结构之后的空间。
好处就是sockaddr_un是变长的,为了不浪费空间,就这样定义。到实际分配unix_address结构的时候按实际的地址大小一并分配空间,那样就可以通过unix_address->name来访问实际的地址。

这样做的具体的优点:
struct unix_address
{
atomic_t refcnt;
int len;
unsigned hash;
void *name;
};

1。name占用空间(4字节)
2。分配空间的时候可以一起分配,但是需要把p->name设置为=p++,访问name的值时需要指针中
转一下


struct unix_address
{
atomic_t refcnt;
int len;
unsigned hash;
struct sockaddr_un name[0];
};
没有上面两个缺点
1。它不占用结构的空间
2。如果访问某个p->name,却可以访问紧接p的内存空间
利用上面两个特性,就可以根据实际的unix域地址大小来一起分配空间,通过p->name访问地址


-------------------------------------------------------------------

| |实际地址|

-------------------------------------------------------------------

^ ^

| |

p name

它可以用来定义一个变长的结构体,比如你可以动态分配这个结构体,并把分配的长度等于sizeof(struct) + len,这样len这么长的内存就可以直接用最后的那个没有实际空间的指针来引用了。

以上摘自:http://blog.chinaunix.net/u/16231/showart_116414.html

 

有人提到这样用malloc函数开辟空间后malloc(sizeof(struct) + len)。再用free释放时会不会出问题?

找到的资料来看,都认为不会:

(1)如果你有一个malloc到的指针,可以看一下它所指的地址,在前面一点有一个指明分配的空间的大小的数字,这个就是所谓的“释放内存大小的量”,如果你不相信的话可以用vc试试,我的确看到过。  
  但是这个数字一般来说不是你malloc或者realloc时候传递的size参数,因为堆分配策略中分配的堆内存不能过于零散,所以一般实际分配的长度是某些特定的值:4B,12B,24B,36B……等等。  
  楼主可以自己再验证一下,关于嵌入式系统,应该比普通的系统更加严格。

(2)free释放空间   的大小存放在什么地方是由堆的实现决定的.  
  如sandrowjw所说,如果堆是采用的buddy算法,其释放大小由内存起始地址决定了  
  如果是其它策略,则这个值可能会存放在指针前的几个字节,也可能存在某个固定的内存区域(只能被堆的实现所访问).

(3)free只传一个指针,是怎么知道要释放的内存大小的呢,有学习过操作系统内存管理的人可能知道,我们申请一块内存的时候,(以下可能不同系统实现不一样):

申请成功,那么系统给我们是一个指针的地址,这个地址里面的某个地方存放着内存块的描述符(包括内存类型和大小)这样,free的时候系统会先读取这个描述符,返回再释放,所以能释放掉所有我们申请的内存,具体详细的还是的学习学习操作系统原理。

当我们得到一个指针的时候,我们可以对其类型做强制转换,这都不影响内存里面的实际空间大小,释放的时候系统还是能安全释放。

可是如果我们对指针地址做了修改,比如:

char *p = (char *)malloc(sizeof(char) * LEN);

int *i = (int *)p;

那么free(i),OK,没问题;

如果

i = (int *)p + 1;

free(i); 那么挂了,呵呵!

就是这样了,地址被你改变了,找不到内存块的描述符了,也就不知道内存的类型和大小,自然也就挂了!

不过这个存放描述符的地址每个系统都不一样(也有可能有一样的,^_^),里面的具体内容也不一样;

  评论这张
 
阅读(433)| 评论(0)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018