malloc返回的类型是void *
然后需要将void *转换为你需要使用的相应类型。
例如如下代码。
-------------------------------------------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct
{
int age;
int sex;
char name[20];
}Node;
typedef struct
{
int age;
int sex;
}Temp;
int main()
{
Node * p_node;
Temp *p_temp;
int i;
printf("Node size:[%d]\n",sizeof(Node));
p_node=(Node *)malloc(sizeof(Node)*10);
for(i=0;i<10;i++)
printf("Node[%d]:age[%d]sex:[%d]name:[%s]\n",i,p_node->age,p_node->sex,p_node->name);
memset(p_node,0,sizeof(Node)*10);
p_temp=(Temp *)(p_node+sizeof(Node));
p_temp->age=10;
printf("age[%d]\n",(p_node+sizeof(Node))->age);
free(p_node);
return 0;
}
-------------------------------------------------------------------------------------
返回的是申请到的内存的首地址,按照概念上这块内存在堆上。
而地址不过是给指针,虽然在赋值的时候进行了强制类型转换,
但是按照C里面的所以有变量不过是一个地址,一种内存块使用的方式定义,(个人理解)所以最终还是对内存的
使用。
1、那这个地方,我将malloc出来的内存是不是可以转换成另外一种类型呢?
2、那个地方为什么一定要强制进行类型转换呢?
3、若是采用一种方式绕过类型检测,会不会对程序有什么危害,比如说内存对齐方面的问题。
PS:上面的结果输出来是 age =10
--
Best Regards,
Dunrong Huang
Dunrong Huang
那个地方我先printf 是调试用的。
那个printf语句没有详细考虑,
写这个例子只是验证一些猜想,引申一下讨论。
不过谢谢您的指出。
----------------------------------
SuperCat
我这个地方 可能需要将一块内存进行多次重用,类似内存池的机制。
可能需要赋值给不同的结构体类型来使用,每次使用前会重新擦零,这样是不是我应该将 Node 定义为void * 然后每次使用前强制转换呢?
貌似以前写某个接口地方用国这种方法,但是这样用会不会造成隐藏的bug呢?
我这里需要频繁的分配内存,操作上W的数据,且这些数据,可能是各种不同的结构,
我的思路1就是利用类似内存池的机制来处理,但是内存池多庞大的一个东东阿,所以我尝试找简化版本的来试试。
思路2,分配一块够大的空间,定义成void * 不停的转换成其他类型,然后用完就擦零,不释放。重复使用,也类似内存池。
思路3 ,估计那些结构也就20来种,穷举这些结构类型定义一个操作集合来操作,不过问题是有些结构可能是不定长度的。
2012/8/16 none_nobody <lyx...@gmail.com>:
--
Best Regards,
Dunrong Huang
另外: 假设 ARM 上 int 是 4B的, int *p = (int*)malloc(sizeof(char)*4); 和 int
*p = (int*)malloc(sizeof(int)); 不一样?
会有问题?
在 2012年8月17日 上午1:03,David pulq <pulq...@gmail.com> 写道:
> hmm,是我举的例子不恰当。。因为for
> arm的libc的实现里malloc一般会对齐到8byte(有兴趣的可以验证一下)所以举的例子不会有问题。只有在类似:
我没有记错的话, uclibc 里面就是根据 sizeof(double) 来对齐的, glibc 的源码没有看过.
> char *buf = malloc(xxx);
> *(int*)(buf+1);
> *(int*)(buf+2);
> *(int*)(buf+3);
如果是这种情况, 一般都是用 uint8_t 之类的 type 来定义的.
#include <stdint.h>
uint8_t *buf = malloc(xxx);
所以, 这个真得靠程序员自觉了.
我想不明白sizeof(char)*4和sizeof(int)有什么区别,malloc只是一个接受参数的普通函数啊。
size_t是implementation defined,如果没记错是32位机4字节,64位机8字节
对齐默认是2 * sizeof(size_t)
每个allocated chunk至少有4/8字节的overhead(就是INTERNAL_SIZE_T)。
#define INTERNAL_SIZE_T size_t
#define SIZE_SZ (sizeof(INTERNAL_SIZE_T))
#define MALLOC_ALIGNMENT (2 * SIZE_SZ)
#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)
#define MIN_CHUNK_SIZE (offsetof(struct malloc_chunk, fd_nextsize))
#define MINSIZE (unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) &
~MALLOC_ALIGN_MASK))
#define request2size(req) \
(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
MINSIZE : \
((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
简化版的malloc_usable_size=chunksize(p)-SIZE_SZ
具体的可以参考glibc/malloc/malloc.c,有很好的注释。
记得有人说过malloc是不是线程安全的问题,注释里说是的,而且在代码里能看到很多mutex_lock和mutex_unlock。
我有一次代码动态链接的参数表不一致,导致内存被破坏了,malloc陷入了死锁,让我百思不得其解。
此外,关于自己为细粒度malloc建立内存池的问题,先看看malloc是不是已经帮忙做了:
The main properties of the algorithms are:
* For large (>= 512 bytes) requests, it is a pure best-fit allocator,
with ties normally decided via FIFO (i.e. least recently used).
* For small (<= 64 bytes by default) requests, it is a caching
allocator, that maintains pools of quickly recycled chunks.
* In between, and for combinations of large and small requests, it does
the best it can trying to meet both goals at once.
* For very large requests (>= 128KB by default), it relies on system
memory mapping facilities, if supported.