在结构本身中存储数组的大小 [英] Storing the size of an array in the structure itself

查看:65
本文介绍了在结构本身中存储数组的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为每个C程序员都可以解决分配数组所带来的malloc

带来的挫败感。特别是,我总是发现这样一个事实:

数组的大小必须单独存储才能成为一场噩梦。


当然有许多解决方案,但它们最终都迫使你们放弃数组语法而不是宏或函数。


现在我有两个问题 - 一个是历史性的,另一种是实用的。


1.)当然malloc(和朋友)必须存储分配给

特定内存分配的大小,如果malloc是要知道在free()发生时释放多少钱?b $ b释放?那么,为什么C库以这样的方式设计

而不是为了提供这些信息呢?或者我在这里严重遗漏了一些东西?


2.)为什么不在前四个字节中存储数组的大小(或

first sizeof(size_t)bytes),然后将指针移到

数组上四个字节?因此有一个:


前4个字节其他所有

[大小] [数据]

/ \

void * blah ---''


那么它应该表现为正常数组,具有额外的优势

知道它的大小。我怀疑的原因是,如果这是一个好主意,我相信它已经被广泛使用了。任何

令人信服的理由避免这种情况?这有点hackery,但

hackery将仅限于分配,调整大小和检查数组大小的函数。


代码可以如下工作:


void *

malloc_array(size_t element_size,size_t items)

{

size_t sz = element_size * items;

void * result = malloc(sz + sizeof(size_t)); / *为数组和大小块分配内存

* /

*((size_t *)result)= items; / *将大小分配给

前几个字节* /

返回sz + sizeof(size_t); / *返回一个指针

指向超出大小块的数组* /

}


size_t

sizeof_array(void * array)

{

return *((size_t *)(array - sizeof(size_t)));

}


这种技术当然也可以用来存储数组中元素的字节大小。哦,是的,为了检测

大小的值是否被意外写过而损坏,可以使用一个幻数(这将再次由相同的技术),

可以参考调试代码。

解决方案

" Wynand Winterbach" < WY **** @ realtimerodeo.net>在消息中写道

news:7b ************************** @ posting.google.c om ...

我认为每个C程序员都可以解决malloc
分配数组带来的挫败感。


我根本没有发现它们令人沮丧。


特别是,我总是发现这样的事实
数组的大小必须分开存储才能成为噩梦。


为什么?为什么比在程序中保持跟踪任何其他信息更加令人沮丧呢?还要注意

用''malloc()'获得的内存本身并不是''数组'',

它只是一个''块'内存,你可能会或不会使用

来存储数组。


当然有很多解决方案,但它们最终都会强迫你要放弃数组语法,转而使用宏或函数。


完全没有。 最佳解决方案是简单地保存您分配的

大小。再一次,分配的内存不需要

用作阵列。


现在我有两个问题 - 一个是历史的,另一个是实际上。

1.)当然malloc(和朋友)必须存储为特定内存分配分配的大小,如果malloc知道在免费时释放多少内容()发生?


''malloc()''的实现当然必须保持''内务管理''

信息。但是每个实现都可以使用最适合目标平台的任何方法自由实现''malloc()''


语言标准仅指示*行为* ''malloc()'',

不是如何实现的。


因此,为什么C库设计成
这样的方式,以免提供这些信息?


想一想。当你打电话给''malloc()''时,你*有*这个信息。

否则你不能告诉它分配多少。


另外,如果你愿意采用非标准和平台特定的方式,那么许多实现确实提供了一个功能来提供你需要的信息

。检查你的文件。

或者我在这里严重遗漏了什么?


我想你只是在偷懒。 :-)

2.)为什么不将数组的大小存储在前四个字节(或第一个sizeof(size_t)字节),然后将指针移动到
数组由四个字节组成?因此有一个:

前4个字节其他一切
[size] [data]
/ \
void * blah ---''


这可能确实是某些实现的方式,

但不是必需的。也许对于给定的体系结构来说,它只是不可能或效率太低。

然后它应该表现为正常状态。数组,


IMO你需要停止自动将分配的内存视为

一个''数组''。它只是分配了内存,可以根据需要使用。


具有
知道其大小的额外优势。


您已分配它,您已经知道它的大小。还要注意

''malloc()''的要求是它分配*至少*

请求的字节数,但它允许分配更多

(通常是为了达到目标

平台的对齐要求和/或效率)。

我在这里有疑问的原因是,如果这是一个好主意,我相信它已经被广泛使用了。


它会不必要地限制实现者以及可能实现C标准库的那些

平台。


避免这种情况的任何令人信服的理由?这有点hackery,但
hackery将局限于分配,调整大小和检查数组大小的函数。


对,这是''hackery''。把事情简单化。只需记住大小。

(将其传递给任何需要它的函数)。


代码可以如下工作:
void *
malloc_array(size_t element_size,size_t items)
{
size_t sz = element_size * items;
void * result = malloc(sz + sizeof(size_t)); / *为数组和大小块分配内存* /
*((size_t *)result)= items; / *将大小分配给前几个字节* /
返回sz + sizeof(size_t); / *将指针返回指向超出大小块的数组* /


size_t
sizeof_array(void * array)
{
return *((size_t *)(array - sizeof(size_t)));
}


如果你想解决所有麻烦,请成为我的客人。但是我不会这么打扰。


这种技术当然也可以用来存储元素的字节大小。阵列。


但是''malloc()'分配的内存不一定是用作数组的


哦,是的,为了检测
尺寸值是否因意外地翻过来而被破坏,可以使用一个幻数(这将再次通过相同的技术添加) ,
可以参考调试代码。




也许有些实现可以做到这一点。但同样,他们并不需要



-Mike




Wynand Winterbach < WY **** @ realtimerodeo.net>写了


我认为每个C程序员都可以解决malloc
分配数组带来的挫败感。特别是,我总是发现这样一个事实:数组的大小必须单独存储才能成为一场噩梦。

梦魇太强大了。分别保持数组大小跟踪是一件轻微的不便。
当然有很多解决方案,但它们最终都迫使你放弃了数组语法支持宏或函数。

所以这些基本上都不是解决方案。如果你想要一个更高级的语言

为你做阵列管理,那么使用C ++。尝试使用某种类型来手动滚动的definearray()宏只会让你的C代码更难以阅读和

来维护。
现在我有两个问题 - 一个是历史的,另一个是实用的。

1.)当然malloc(和朋友)必须存储为特定内存分配分配的大小,如果malloc要知道多少到
在free()发生时解除分配?因此,为什么C库以不使这些信息可用的方式设计?或者我在这里严重遗漏了什么?

我不会说严重缺失。 ANSI C很容易要求库提供一个msize()函数,并且可能已经添加了

次要开销。然而,在他们的智慧中,他们决定反对这一点,可能是为了保持旧的实现业务。
2.)为什么不将数组的大小存储在前四个字节中(或者
第一个sizeof(size_t)字节),然后将指针移到四个字节上的
数组?



在很多库中都有这样做。自己做的问题是

,这不是常规,所以它会混淆任何阅读你的

代码的人。你还必须考虑到,严格来说,如果你分配一个数组

的结构对齐问题可能会阻止你抓住前四个
字节。这个问题可以解决,但它是另一个摆弄和
$ b $丑陋。


malloc()和free()提供一个干净的,概念上的简单的一对例程

用于内存分配和释放。一旦你开始搞乱它们你就会开始破坏C语言的基本简单性。


文章< 7b *** ***********************@posting.google.com>

Wynand Winterbach< wy **** @ realtimerodeo达网络>写道:

1。)当然malloc(和朋友)必须存储为特定内存分配分配的大小,如果malloc要知道在免费时释放多少内容()发生?


也许吧。或者,当你调用free()而不是明确存储时,大小是通过一个漫长的,辛苦的
过程来计算的。


此外,大小做什么你怀疑不同的malloc()

实现还记得:你要求的大小,或者你得到的大小

? (你可能会得到比你要求的更多的东西 - 一些malloc()s

在某些情况下会缩小尺寸。例如,某些快速

但有些空间 - 当你要求2100时,华丽的malloc()s会给你4096字节

。事实上,在很多情况下,几乎所有的malloc()都可能是
,如果没有非常严重。)


这些都不会禁止未来的标准C要求

某种类型的mallocsize函数,但是对于mallocsize()是否必须为所有成功的
malloc(n)调用返回n,或者它是否可以返回round_up(n),需要一些

辩论)。它可能还会限制未来的实现者(如果mallocsize()是

预期要快,和/或如果它必须返回n而不是

rounded_up(n))。


所有这一切加起来:这肯定是可能的,而不一定是

a坏主意,但它并不像它最初看起来那么简单。

2.)为什么不将数组的大小存储在前四个字节中(或者
第一个sizeof(size_t)字节),然后将指针移动到
数组四个字节?因此有一个:

前4个字节其他一切
[size] [data]
/ \
void * blah ---''




如果您在Sun SPARCstation上尝试此操作(在32位size_t模式下),

您会发现此技术适用于 ints,longs和

浮动,但是对于long long和doubles是失败的。 (在64位

是硬件需要8字节对齐8-字节数据

类型通过ldd / std / ldx / stx / lddf / stdf加载或存储,并且

编译器倾向于将这些指令用于这些数据类型(使用

一些例外 - 类型为double的函数参数未对齐

在某些子例程调用协议中。


许多其他架构也有类似的限制。甚至

否则相当自由的x86架构对MMX和SSE指令有强烈的对齐

限制(至少如果你想要
想要使用快速MOVAPS指令)。这里所需的

对齐不是8,而是16字节。 (对于特殊的

SMP指令来说,情况更糟,其中良好的性能使用128字节对齐!)


有一些不可移植的方法可以做到这一点工作 - 基本上你需要

来为分配的空间添加一个size_t的联合,并且

机器的限制性最强的数据类型(无论是什么)或者一个

最大限制类型大小的字节数组(无论是

又是什么)。不幸的是,C标准在找到这种限制最多的类型或其大小时,没有给你任何帮助

。这样的类型/大小

实际上必须存在(因为malloc()有效),但是标准确实没有将它导出到用户代码。

-

In-Real-Life:风河系统Chris Torek

美国犹他州盐湖城(40°39.22''N,111°50.29 ''W)+1 801 277 2603

电子邮件:忘了它 http://web.torek.net/torek/index.html

由于垃圾邮件发送者,阅读电子邮件就像在垃圾中搜索食物一样。


I think every C programmer can relate to the frustrations that malloc
allocated arrays bring. In particular, I''ve always found the fact that
the size of an array must be stored separately to be a nightmare.

There are of course many solutions, but they all end up forcing you to
abandon the array syntax in favour of macros or functions.

Now I have two questions - one is historical, and the other practical.

1.) Surely malloc (and friends) must store the size allocated for a
particular memory allocation, if malloc is to know how much to
deallocate when a free() occurs? Thus, why was the C library designed
in such a fashion as not to make this information available? Or I am
seriously missing something here?

2.) Why not store the size of the array in its first four bytes (or
first sizeof( size_t ) bytes ), and then shift the pointer to the
array on by four bytes? Thus one has:

first 4 bytes everything else
[ size ][ data ]
/\
void * blah ---''

Then it should behave as a "normal" array, with the added advantage of
knowing its size. The reason I have doubts here, is that if this was
such a good idea, I''m sure it would already have been widely used. Any
compelling reason for avoiding this? This is a bit of hackery, but the
hackery will be confined to the functions for allocating, resizing and
checking the size of the array.

The code could work as follows:

void*
malloc_array( size_t element_size, size_t items )
{
size_t sz = element_size * items;
void* result = malloc( sz + sizeof( size_t ) ); /* allocate memory
for array and for size chunk */
*((size_t*) result) = items; /* assign the size to
the first few bytes */
return sz + sizeof( size_t ); /* return a pointer
to the array pointing just beyond size chunk */
}

size_t
sizeof_array( void *array )
{
return *( (size_t*) (array - sizeof( size_t )) );
}

This technique of course could also be used to store the byte size of
the elements in the array. Oh yes, and in order to detect whether the
size value was corrupted by accidentally writing over it, one could
use a magic number (which would again be added by the same technique),
which could be consulted with debugging code.

解决方案

"Wynand Winterbach" <wy****@realtimerodeo.net> wrote in message
news:7b**************************@posting.google.c om...

I think every C programmer can relate to the frustrations that malloc
allocated arrays bring.
I don''t find them frustrating at all.

In particular, I''ve always found the fact that
the size of an array must be stored separately to be a nightmare.
Why? Why is it any more ''frustrating'' than keeping track
of any other piece of information in a program? Also note
that memory obtained with ''malloc()'' isn''t inherently an ''array'',
it''s just a ''chunk'' of memory, which you might or might not use
to store an array.

There are of course many solutions, but they all end up forcing you to
abandon the array syntax in favour of macros or functions.
Not at all. The ''best'' solution imo is to simply save the
size you allocate. And again, allocated memory isn''t required
to be used as an array.

Now I have two questions - one is historical, and the other practical.

1.) Surely malloc (and friends) must store the size allocated for a
particular memory allocation, if malloc is to know how much to
deallocate when a free() occurs?
An implementation of ''malloc()'' must of course keep ''housekeeping''
information. But each implementation is free to implement ''malloc()''
with whatever method is most appropriate for the target platform.
The language standard only dictates the *behavior* of ''malloc()'',
not how it is to be implemented.

Thus, why was the C library designed
in such a fashion as not to make this information available?
Think about it. WHen you call ''malloc()'', you *have* this information.
Otherwise you couldn''t tell it how much to allocate.

Also, if you''re willing to go nonstandard and platform-specific,
many implementations do provide a function to give the information
you''re after. Check your documentation.
Or I am
seriously missing something here?.
I think you''re just being lazy. :-)

2.) Why not store the size of the array in its first four bytes (or
first sizeof( size_t ) bytes ), and then shift the pointer to the
array on by four bytes? Thus one has:

first 4 bytes everything else
[ size ][ data ]
/\
void * blah ---''
This might indeed be the way it is done for some implementations,
but it''s not required. Perhaps for a given architecture it''s
simply not possible or too inefficient.
Then it should behave as a "normal" array,
IMO you need to stop automatically thinking of allocated memory as
an ''array''. It''s simply allocated memory, to be used as desired.

with the added advantage of
knowing its size.
You allocated it, you already know its size. Also note that
the requirement for ''malloc()'' is that it allocate *at least*
the number of requested bytes, but it''s allowed to allocate more
(would typically be done in the interest of meeting the target
platform''s alignment requirements and/or of efficiency).
The reason I have doubts here, is that if this was
such a good idea, I''m sure it would already have been widely used.
It would unnecessarily restrict implementors and possibly which
platforms the C standard library could be implemented for.

Any
compelling reason for avoiding this? This is a bit of hackery, but the
hackery will be confined to the functions for allocating, resizing and
checking the size of the array.
Right, it''s ''hackery''. Keep It Simple. Just Remember The Size.
(Pass it to any functions that need it).

The code could work as follows:

void*
malloc_array( size_t element_size, size_t items )
{
size_t sz = element_size * items;
void* result = malloc( sz + sizeof( size_t ) ); /* allocate memory
for array and for size chunk */
*((size_t*) result) = items; /* assign the size to
the first few bytes */
return sz + sizeof( size_t ); /* return a pointer
to the array pointing just beyond size chunk */
}

size_t
sizeof_array( void *array )
{
return *( (size_t*) (array - sizeof( size_t )) );
}
If you want to go to all that trouble, be my guest. But I wouldn''t
bother.

This technique of course could also be used to store the byte size of
the elements in the array.
But the memory allocated by ''malloc()'' needn''t necessarily be
used as an array.

Oh yes, and in order to detect whether the
size value was corrupted by accidentally writing over it, one could
use a magic number (which would again be added by the same technique),
which could be consulted with debugging code.



Perhaps some implementations do this. But again, they''re not
required to.

-Mike



"Wynand Winterbach" <wy****@realtimerodeo.net> wrote


I think every C programmer can relate to the frustrations that malloc
allocated arrays bring. In particular, I''ve always found the fact that
the size of an array must be stored separately to be a nightmare.
"Nightmare" is way too strong. It is a slight inconvenience to have to keep
track of array size separately.
There are of course many solutions, but they all end up forcing you to
abandon the array syntax in favour of macros or functions.
So these are basically non-solutions. If you want a higher level language
that does array management for you, then use C++. Trying to use some sort to
hand-rolled definearray() macro just makes your C code harder to read and
to maintain.
Now I have two questions - one is historical, and the other practical.

1.) Surely malloc (and friends) must store the size allocated for a
particular memory allocation, if malloc is to know how much to
deallocate when a free() occurs? Thus, why was the C library designed
in such a fashion as not to make this information available? Or I am
seriously missing something here?
I wouldn''t say "seriously missing". ANSI C could easily have demanded that
the library provide an msize() function, and it could have been added with
minor overhead. However in their wisdom they decided against this, probably
to keep old implementations in business.
2.) Why not store the size of the array in its first four bytes (or
first sizeof( size_t ) bytes ), and then shift the pointer to the
array on by four bytes?


Internally a lot of libraries do this. The problem with doing it yourself is
that it is not the convention, so it will confuse anyone else reading your
code. You''ve also got to consider that, strictly, if you allocate an array
of structures alignment issues may preclude you from grabbing the first four
bytes. This problem can be solved, but it''s another bit of fiddling and
ugliness.

malloc() and free() provide a clean, conceptually simple pair of routines
for memory allocation and deallocation. Once you start messing with them you
also begin to destroy the essential simplicity of the C language.


In article <7b**************************@posting.google.com >
Wynand Winterbach <wy****@realtimerodeo.net> writes:

1.) Surely malloc (and friends) must store the size allocated for a
particular memory allocation, if malloc is to know how much to
deallocate when a free() occurs?
Perhaps. Or perhaps the size is computed via a long, painstaking
process when you call free(), rather than being stored explicitly.

Moreover, which size do you suspect that different malloc()
implementations remember: the size you asked for, or the size
you got? (You may get more than you asked for -- some malloc()s
will round the size up in some cases. For instance, certain fast
but somewhat-space-wasteful malloc()s will give you 4096 bytes
when you ask for 2100. Indeed, almost all malloc()s probably
round up in many cases, if not quite so severely.)

None of this would prohibit a future Standard C from requiring
some kind of "mallocsize" function, but it would require some
debate as to whether mallocsize() must return n for all successful
malloc(n) calls, or whether it could return rounded_up(n). It
might also constrain future implementors (if mallocsize() were
"expected" to be fast, and/or if it must return n rather than
rounded_up(n)).

All of this adds up to: "It is certainly possible, and not necessarily
a bad idea, but it is not as simple as it looks at first either."
2.) Why not store the size of the array in its first four bytes (or
first sizeof( size_t ) bytes ), and then shift the pointer to the
array on by four bytes? Thus one has:

first 4 bytes everything else
[ size ][ data ]
/\
void * blah ---''



If you try this on a Sun SPARCstation (in 32-bit "size_t" mode),
you will find that this technique works for "int"s, "longs", and
"floats", but fails for "long long"s and "double"s. (In 64-bit
mode it will work if size_t is itself a 64-bit type.) The reason
is that the hardware requires 8-byte alignment for 8-byte data
types loaded or stored via ldd/std/ldx/stx/lddf/stdf, and the
compiler tends to use those instructions for those datatypes (with
some exceptions -- function parameters of type "double" are misaligned
in some of the subroutine-call protocols).

Many other architectures have similar restrictions. Even the
otherwise-quite-liberal x86 architecture has strong alignment
constraints for its MMX and SSE instructions (at least if you
want to use the "fast" MOVAPS instruction). Here the required
alignment is not 8 but 16 bytes. (It gets even worse for special
SMP instructions, where "good performance" uses 128-byte alignment!)

There are nonportable ways to make this work -- basically you need
to prefix the allocated space with a union of a single size_t, and
the machine''s most restrictive data type (whatever that is) or an
array of bytes of the size of the most restrictive type (whatever
that is, again). Unfortunately, the C Standard gives you no help
in finding this most-restrictive type or its size. Such a type/size
must in fact exist (because malloc() works), but the Standard does
not export it to user code.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22''N, 111°50.29''W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.


这篇关于在结构本身中存储数组的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆