有没有人品评一下这个malloc的实现?

fallening 2010-02-05 08:11:03
文件在这里,太大了,不发。自己下载
...全文
256 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
liuxiaobing2008 2010-02-06
  • 打赏
  • 举报
回复
帮顶一下~~~
rularys 2010-02-06
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 jackyjkchen 的回复:]
也许是Windows和unix的差异,我感觉错误的文本提示不应该在函数体里,还明确的输出到stderr……若在Windows编程,这样的话会瞬间闪一个黑框
[/Quote]

应该不会这样,stderr 和stdout等在window下也是通用的输出缓冲,在没有控制台的情况下,系统不会把它们绑到不存在缓冲里去。库里用这些应该是可以通用的,具体会输出到哪里,由应用来决定——控制台的话默认会被绑到控制台,否则的话还可以手工绑定比如重定向到日志文件
Wolf0403 2010-02-06
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 fallening 的回复:]
引用 17 楼 jackyjkchen 的回复:
如果这样的话效率岂不会很低……当然Windows下文件IO比控制台IO快。

我的意思是,如果我用printf刷屏,所有东西都会存进文件?

会写进stdout和stderr中的一个去吧,不过应该会有缓冲的,并不是随写随显;



[/Quote]
首先,jc 同志完全没有理解这里“文件”是一个虚指的接口,以为是文件系统中一个可以被再次打开读取内容的实体。
然后,stdout 和 stderr 的缓冲策略是 glibc 指定的,out 是 line buffer,err 是 no buffer,也就是随显
crystal_dark 2010-02-05
  • 打赏
  • 举报
回复
up
fallening 2010-02-05
  • 打赏
  • 举报
回复
glibc的malloc更长,可能是因为注释得更详细的原因,感兴趣的可以在这里下载到
fallening 2010-02-05
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 jackyjkchen 的回复:]
如果这样的话效率岂不会很低……当然Windows下文件IO比控制台IO快。

我的意思是,如果我用printf刷屏,所有东西都会存进文件?
[/Quote]
会写进stdout和stderr中的一个去吧,不过应该会有缓冲的,并不是随写随显;



yzx714 2010-02-05
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 fallening 的回复:]
在linux/unix下,设备就是文件
[/Quote]或者说以文件来访问设备
jackyjkchen 2010-02-05
  • 打赏
  • 举报
回复
如果这样的话效率岂不会很低……当然Windows下文件IO比控制台IO快。

我的意思是,如果我用printf刷屏,所有东西都会存进文件?
fallening 2010-02-05
  • 打赏
  • 举报
回复
在linux/unix下,设备就是文件
jackyjkchen 2010-02-05
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 fallening 的回复:]
引用
$ ls /dev/std* -al
lrwxrwxrwx 1 root root 15 Dec 20 11:37 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Dec 20 11:37 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Dec 20 11:37 /dev/stdout -> /proc/self/fd/1


这就是linux下的stderr, stdin 和 stdout了
[/Quote]
问一下,这些是文件吧,如果linux控制台存在,也会输出到这些文件里?
fallening 2010-02-05
  • 打赏
  • 举报
回复
[Quote]
$ ls /dev/std* -al
lrwxrwxrwx 1 root root 15 Dec 20 11:37 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Dec 20 11:37 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Dec 20 11:37 /dev/stdout -> /proc/self/fd/1
[/Quote]

这就是linux下的stderr, stdin 和 stdout了
mLee79 2010-02-05
  • 打赏
  • 举报
回复
没控制台时, 输出当然会失败了...
当然, 如果你写少量的内容, 就会发现返回值好像是成功了, 那只是因为它的缓冲区还没填满...
win 的控制台真垃圾...
jackyjkchen 2010-02-05
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 mlee79 的回复:]
不是很喜欢...
Win也没啥问题, 没控制台的时候不会有黑框...
即使是GUI程序也创建控制台, 看不到黑框就不放心的飘过...


[/Quote]
可能是我多虑了,stdout和stderr应该不会自己创建控制台,但这个时候输出到哪里呢?

干脆,我写的后台函数全都没有内部的错误提示,只提供返回值,错误处理全在外面,控制台程序还是Windows程序自己控制
Proteas 2010-02-05
  • 打赏
  • 举报
回复
win nt 下的 malloc.c


#include <cruntime.h>
#include <assert.h>
#include <heap.h>
#include <malloc.h>
#include <os2dll.h>
#include <stddef.h>

#ifndef _POSIX_
#include <new.h>
_PNH _pnhHeap = NULL; /* pointer to new() handler */
#endif

#ifdef MTHREAD

void * _CALLTYPE1 malloc (
size_t size
)
{
void *pret;

#ifndef _POSIX_
for (;;)
{
#endif
/* lock the heap
*/
_mlock(_HEAP_LOCK);

/* do the allocation
*/
pret = _malloc_lk(size);

/* unlock the heap
*/
_munlock(_HEAP_LOCK);

#ifndef _POSIX_
if (pret || _pnhHeap == NULL || (*_pnhHeap)(size) == 0)
#endif
return(pret);

#ifndef _POSIX_
}
#endif /* ndef _POSIX_ */
}


void * _CALLTYPE1 _malloc_lk (
size_t size
)

#else /* ndef MTHREAD */

void * _CALLTYPE1 malloc (
size_t size
)

#endif /* MTHREAD */

#ifdef _CRUISER_

{
char *pblck;
_PBLKDESC pdesc;
size_t dist;

/* round size up to the nearest whole number of dwords
*/
size = _ROUND2(size, 4);

/* first try allocating a block of size bytes
*/
if ( ((pblck = _flat_malloc(size)) == NULL) || (size > _SEGSIZE_) ||
(_DISTTOBNDRY(pblck) >= size) )
/* all done!
*/
goto done;
else
/* doesn't meet requirements, free the allocation back to the
* heap
*/
_free_lk(pblck);

/* now, try allocating a block of 2*size bytes. if successful, the
* allocated block is guaranteed to contain a region of size bytes
* which does not cross a 64 K boundary.
*/
if ( (pblck = _flat_malloc(2*size)) == NULL )
/* allocation failed, return NULL to the caller
*/
goto done;

/* set pdesc to point to the descriptor for the allocation block
*/
pdesc = _BACKPTR(pblck);

/* find a subregion of at least size bytes which does not cross a
* 64 Kb boundary and build a heap block around it. set pblck to
* point to to allocation area of the block and pdesc to point to
* its descriptor
*/
if ( (dist = _DISTTOBNDRY(pblck)) < size ) {
/* the subregion from pblck to (pblck + size) crosses a 64 Kb
* boundary, but the subregion from (pblck + dist) to (pblck +
* dist + size) cannot (it starts on one). therefore, split
* the block into two heap blocks, with the later block
* starting at (pblck + dist - _HDRSIZE), and free the first
* block.
*/
_heap_split_block(pdesc, dist - _HDRSIZE);
_free_lk(pblck);
pdesc = pdesc->pnextdesc;
_SET_INUSE(pdesc);
pblck += dist;
}

/* pblck and pdesc are now bound to allocation block whose first size
* bytes do not cross any 64 Kb boundary. only detail is the block
* may be too large so...
*/
#ifdef _OLDROVER_

_heap_split_block(pdesc, size);
_SET_FREE(pdesc->pnextdesc);
_heap_advance_rover();

#else /* ndef _OLDROVER_ */

if ( _BLKSIZE(pdesc) > size ) {
_heap_split_block(pdesc, size);
_SET_FREE(pdesc->pnextdesc);
_heap_desc.proverdesc = pdesc->pnextdesc;
}

#endif /* _OLDROVER_ */

done:
return(pblck);
}


void * _CALLTYPE1 _flat_malloc (
size_t size
)

#endif /* _CRUISER_ */

{
_PBLKDESC pdesc;

/* validate size
*/
/***** COMMENTED OUT UNTIL _HEAP_MAXREQ IS DEFINED
if ( size > _HEAP_MAXREQ )
return(NULL);
*****/

/* round requested size
*/
size = _ROUND2(size, 4);

#if !defined(_POSIX_) && !defined(MTHREAD)
for (;;)
{
#endif /* !_POSIX && !MTHREAD */
/* try to find a big enough free block
*/
if ( (pdesc = _heap_search(size)) == NULL )
if ( _heap_grow(size) != -1 ) {
/* try finding a big enough free block again. the
* success of the call to _heap_grow should guarantee
* it, but...
*/
if ( (pdesc = _heap_search(size)) == NULL )
/* something unexpected, and very bad, has
* happened. abort!
*/
_heap_abort();
}
#if !defined(_POSIX_) && !defined(MTHREAD)
else if (!_pnhHeap || (*_pnhHeap)(size) == 0)
return(NULL);
else
continue;
else
break; /* success! */
}
#else /* _POSIX || MTHREAD */
else
return(NULL);
#endif /* !_POSIX && !MTHREAD */

/* carve the block into two pieces (if necessary). the first piece
* shall be of the exact requested size, marked inuse and returned to
* the caller. the leftover piece is to be marked free.
*/
if ( _BLKSIZE(pdesc) != size ) {
/* split up the block and free the leftover piece back to
* the heap
*/
_heap_split_block(pdesc, size);
_SET_FREE(pdesc->pnextdesc);
}

/* mark pdesc inuse
*/
_SET_INUSE(pdesc);

/* check proverdesc and reset, if necessary
*/
#ifdef _OLDROVER_

_heap_advance_rover();

#else /* ndef _OLDROVER_ */

_heap_desc.proverdesc = pdesc->pnextdesc;

#endif /* _OLDROVER_ */

return( (void *)((char *)_ADDRESS(pdesc) + _HDRSIZE) );
}


void _CALLTYPE1 _heap_split_block (
REG1 _PBLKDESC pdesc,
size_t newsize
)
{
REG2 _PBLKDESC pdesc2;

assert(("_heap_split_block: bad pdesc arg", _CHECK_PDESC(pdesc)));
assert(("_heap_split_block: bad newsize arg", _ROUND2(newsize,4) == newsize));

/* carve the block into two pieces (if possible). the first piece
* is to be exactly newsize bytes.
*/
if ( _BLKSIZE(pdesc) > newsize ) {
/* get an empty decriptor
*/
_GETEMPTY(pdesc2)

/* set it up to manage the second piece and link it in to
* the list
*/
pdesc2->pblock = (void *)((char *)_ADDRESS(pdesc) + newsize +
_HDRSIZE);
*(void **)(pdesc2->pblock) = pdesc2;
pdesc2->pnextdesc = pdesc->pnextdesc;
pdesc->pnextdesc = pdesc2;
}
}

#ifdef _OLDROVER_

void _CALLTYPE1 _heap_advance_rover(void)
{
REG1 _PBLKDESC pdesc;

/* check proverdesc and advance it, if necessary
*/

#ifdef _CRUISER_ /* CRUISER TARGET */

if ( !_IS_FREE(_heap_desc.proverdesc) && (_heap_desc.proverdesc !=
&_heap_desc.sentinel) ) {

#else /* ndef _CRUISER_ */

#ifdef _WIN32_

if ( _heap_desc.proverdesc != &_heap_desc.sentinel &&
(!_IS_FREE(_heap_desc.proverdesc) ||
_BLKSIZE(_heap_desc.proverdesc) <= 8)) {

#else /* ndef _WIN32_ */

#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!

#endif /* _WIN32_ */

#endif /* _CRUISER_ */

/* set pdesc to point to the descriptor for the next free
* block, if any, or &sentinel, otherwise.
*/
for ( pdesc = (_heap_desc.proverdesc)->pnextdesc ;
#ifdef _CRUISER_ /* CRUISER TARGET */
!(_IS_FREE(pdesc)) && (pdesc != &_heap_desc.sentinel) ;
#else /* ndef _CRUISER_ */
#ifdef _WIN32_
pdesc != &_heap_desc.sentinel &&
(!(_IS_FREE(pdesc)) || _BLKSIZE(pdesc) <= 8) ;
#else /* ndef _WIN32_ */

#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!

#endif /* _WIN32_ */

#endif /* _CRUISER_ */
pdesc = pdesc->pnextdesc )
;

/* update proverdesc with pdesc
*/
_heap_desc.proverdesc = pdesc;
}
}

#endif /* _OLDROVER_ */
mLee79 2010-02-05
  • 打赏
  • 举报
回复
不是很喜欢...
Win也没啥问题, 没控制台的时候不会有黑框...
即使是GUI程序也创建控制台, 看不到黑框就不放心的飘过...

jackyjkchen 2010-02-05
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 fallening 的回复:]
jack,你发错了帖子?
[/Quote]
没有,malloc里面有wrterror("out of memory");这一句,wrterror是输出到stderr的吧;

同样calloc里面有fprintf(stderr,"OOOOPS");

说过了,unix方面我是不太了解,可能这么做没错,但是Windows平台如果这样的话可能会有问题。
DontKissBossAss 2010-02-05
  • 打赏
  • 举报
回复
,这么长的代码?就实现一个malloc?Orz
fallening 2010-02-05
  • 打赏
  • 举报
回复
jack,你发错了帖子?
jackyjkchen 2010-02-05
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 fallening 的回复:]
引用 2 楼 jackyjkchen 的回复:
也许是Windows和unix的差异,我感觉错误的文本提示不应该在函数体里,还明确的输出到stderr……若在Windows编程,这样的话会瞬间闪一个黑框

????????????????????
[/Quote]
我没记错的话,stderr默认也是控制台输出吧,正如同我不会简单用MessageBox做错误输出,同样也不会用控制台做错误输出,因为我不清楚我的程序子系统是Winddows还是Console,试想窗口程序闪cmd黑框或者控制台程序弹出一个对话框都很不爽的,Windows是这样,unix没经验。
mostmark 2010-02-05
  • 打赏
  • 举报
回复
加载更多回复(4)

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧