Sorry! Newsreaders Problems!
Here is the message again.
-------------------------------
Hi,
I am trying to get the actual length of a dynamically allocated array.
Apparently
#define NUMELEMS(arr) (sizeof(arr)/sizeof(arr)[0])
works only for statically allocated ones.
I need to very frequently, dinamically allocate arrays, and need to know what the actual length of the array is.
Is there a way, other than checking if the memory allocation function returns -1?
How do you do this?
Thanks
//---------- CODE ---------------------
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <conio.h> // Not ANSI Library
char yn;
#define wait(ext) { printf("\n Continue? (y/n)"); if((yn=getch())=='n')goto ext; };
// --------------------
#define BLXLNGTH 26
#define NUMELEMS(arr) (sizeof(arr)/sizeof(arr)[0])
unsigned int *expandAr_uint(unsigned int *itAr, int itBlxLngth, int itBlx){
unsigned int *itTmpAr = (unsigned int *)calloc(itBlx*itBlxLngth, sizeof(unsigned int));
memcpy(itTmpAr,itAr,(itBlx - 1)*itBlxLngth*sizeof(unsigned int));
free(itAr);
return itTmpAr;
}
char *expandAr_char(char *chAr, int itBlxLngth, int itBlx){
char *chTmpAr = (char *)calloc(itBlx*itBlxLngth + 1, sizeof(char));
memcpy(chTmpAr,chAr,(itBlx - 1)*itBlxLngth*sizeof(char));
free(chAr);
return chTmpAr;
}
int main( void ){
char *chBffr;
unsigned int *uitFfstDif;
int itI, itJ;
int itBlxLngth= BLXLNGTH;
char chBffr02[BLXLNGTH + 1];
unsigned int uitFfstDif02[2*BLXLNGTH];
// __ stress testing loop. checking for memory leaks
for(itJ = 0; itJ < 1; ++itJ){
// ---------------- char array ------------------
// __ Initial Size
chBffr= (char *)calloc(itBlxLngth + 1, sizeof(char));
fprintf(stdout,"\n\n Size of char array chBffr is: %d",sizeof(chBffr));
fprintf(stdout,"\n Size of char array chBffr is: %d",sizeof(*chBffr));
for(itI = 0; (itI < itBlxLngth); ++itI){ chBffr[itI] = (char)(itI + 65); }
chBffr[itBlxLngth] = '\0';
fprintf(stdout,"\n Content of initial array is: %s, length is: %d",chBffr, strlen(chBffr));
fprintf(stdout,"\n NUMELEMS(chBffr) = %d",NUMELEMS(chBffr));
// __ New Size
chBffr= expandAr_char(chBffr,itBlxLngth,2);
fprintf(stdout,"\n New size of char array chBffr is: %d",sizeof(chBffr));
fprintf(stdout,"\n New size of char array chBffr is: %d",sizeof(*chBffr));
for(itI = 0; (itI < itBlxLngth); ++itI){ chBffr[itI] = (char)(itI + 65); }
for(itI = 0; (itI < itBlxLngth); ++itI){ chBffr[itI + itBlxLngth] = (char)(itI + 97); }
chBffr[2*itBlxLngth + 1] = '\0';
fprintf(stdout,"\n Content of expanded array is: %s, length is: %d",chBffr, strlen(chBffr));
// ---------------- int array ------------------
// __ Initial Size
uitFfstDif = (unsigned int *)calloc(itBlxLngth,sizeof(unsigned int));
fprintf(stdout,"\n\n Size of unsigned int array uitFfstDif is: %d",sizeof(uitFfstDif));
fprintf(stdout,"\n Size of unsigned int array uitFfstDif is: %d",sizeof(*uitFfstDif));
for(itI = 0; (itI < itBlxLngth); ++itI){ uitFfstDif[itI] = (unsigned int)(itI + 65); }
fprintf(stdout,"\n Content of initial array is:\n");
for(itI = 0; (itI < itBlxLngth); ++itI)fprintf(stdout,"(%d,%d) ",itI,uitFfstDif[itI]);
// fprintf(stdout,"\n uitFfstDif[%d]=%d",2*itBlxLngth,uitFfstDif[2*itBlxLngth]); // Reading an Off value
// __ New Size
uitFfstDif = expandAr_uint(uitFfstDif,itBlxLngth,2);
fprintf(stdout,"\n Size of unsigned int array uitFfstDif is: %d",sizeof(uitFfstDif));
fprintf(stdout,"\n Size of unsigned int array uitFfstDif is: %d",sizeof(*uitFfstDif));
for(itI = 0; (itI < itBlxLngth); ++itI){ uitFfstDif[itI] = (unsigned int)(itI + 65); }
for(itI = 0; (itI < itBlxLngth); ++itI){ uitFfstDif[itI + itBlxLngth] = (unsigned int)(itI + 97); }
fprintf(stdout,"\n Content of initial array is:\n");
for(itI = 0; (itI < 2*itBlxLngth); ++itI)fprintf(stdout,"(%d,%d) ",itI,uitFfstDif[itI]);
itBlxLngth *= 2;
}
fprintf(stdout,"\n NUMELEMS(chBffr02) = %d",NUMELEMS(chBffr02));
fprintf(stdout,"\n NUMELEMS(uitFfstDif02) = %d",NUMELEMS(uitFfstDif02));
wait(LblEnd);
LblEnd:;
fprintf(stdout,"\n");
return(0);
}
> I am trying to get the actual length of a dynamically allocated array.
>
> Apparently
>
> #define NUMELEMS(arr) (sizeof(arr)/sizeof(arr)[0])
>
> works only for statically allocated ones.
It's not a matter of how it's allocated, it's a matter of how you
know about it. If you have a pointer, its size is not dependent
on how much space is allocated for it. This does mean that
sizeof will never work on an array that is dynamically allocated.
Incidentally, a function never takes an array as a parameter,
although sometimes it looks like it. Any apparent array
parameters are actually pointers. So, within a function declared
as
void function (int foo[X])
for any number X or even with X omitted, the expression
sizeof foo / sizeof *foo
will have a rather useless result because the function
declaration is equivalent to
void function (int *foo)
--
"When in doubt, treat ``feature'' as a pejorative.
(Think of a hundred-bladed Swiss army knife.)"
--Kernighan and Plauger, _Software Tools_
Sure, by-definition. Don't mix pointers and arrays. There are different
beasts.
> I need to very frequently, dinamically allocate arrays, and need to know
what the actual length of the array is.
You asked for a length, you have it, or a NULL. It is your responsability.
> Is there a way, other than checking if the memory allocation function
returns -1?
-1 ? What do you mean. malloc() returns NULL on error, not -1 at all. Have
you opened a C-manual?
>//---------- CODE ---------------------
>
>#include <stdio.h>
>#include <stdlib.h>
>#include <memory.h>
What is this ?
>#include <string.h>
>
>#include <conio.h> // Not ANSI Library
If so, remove it before posting to CLC. Also avoid //. Everybody don't have
a C99 compiler.
>char yn;
>#define wait(ext) { printf("\n Continue? (y/n)"); if((yn=getch())=='n')goto
ext; };
Ugly. What's wrong with getchar()? Do you really need that bloddy goto?
>// --------------------
>
>#define BLXLNGTH 26
Sounds like Welsh. How do you pronounce it?
>#define NUMELEMS(arr) (sizeof(arr)/sizeof(arr)[0])
or
#define NUMELEMS(arr) (sizeof(arr)/sizeof *(arr))
Works on arrays only.
>unsigned int *expandAr_uint(unsigned int *itAr, int itBlxLngth, int
lx){
> unsigned int *itTmpAr = (unsigned int *)calloc(itBlx*itBlxLngth, sizeof(unsigned int));
> memcpy(itTmpAr,itAr,(itBlx - 1)*itBlxLngth*sizeof(unsigned int));
> free(itAr);
> return itTmpAr;
>}
You are ready for IOCCC! Your code is unreadable. I surrender.
For braves, here is a reindented version:
/* ---------- CODE --------------------- */
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <conio.h> /* Not ANSI Library */
char yn;
#define wait(ext) { printf("\n Continue? (y/n)"); if((yn=getch())=='n')goto ext; }
;
/* -------------------- */
#define BLXLNGTH 26
#define NUMELEMS(arr) (sizeof(arr)/sizeof(arr)[0])
unsigned int *expandAr_uint (unsigned int *itAr, int itBlxLngth, int itBlx)
{
unsigned int *itTmpAr = (unsigned int *) calloc (itBlx * itBlxLngth,
sizeof (unsigned int));
memcpy (itTmpAr, itAr, (itBlx - 1) * itBlxLngth * sizeof (unsigned int));
free (itAr);
return itTmpAr;
}
char *expandAr_char (char *chAr, int itBlxLngth, int itBlx)
{
char *chTmpAr = (char *) calloc (itBlx * itBlxLngth + 1, sizeof (char));
memcpy (chTmpAr, chAr, (itBlx - 1) * itBlxLngth * sizeof (char));
free (chAr);
return chTmpAr;
}
int main (void)
{
char *chBffr;
unsigned int *uitFfstDif;
int itI, itJ;
int itBlxLngth = BLXLNGTH;
char chBffr02[BLXLNGTH + 1];
unsigned int uitFfstDif02[2 * BLXLNGTH];
/* __ stress testing loop. checking for memory leaks */
for (itJ = 0; itJ < 1; ++itJ)
{
/* ---------------- char array ------------------ */
/* __ Initial Size */
chBffr = (char *) calloc (itBlxLngth + 1, sizeof (char));
fprintf (stdout, "\n\n Size of char array chBffr is: %d", sizeof
(chBffr));
fprintf (stdout, "\n Size of char array chBffr is: %d", sizeof
(*chBffr));
for (itI = 0; (itI < itBlxLngth); ++itI)
{
chBffr[itI] = (char) (itI + 65);
}
chBffr[itBlxLngth] = '\0';
fprintf (stdout, "\n Content of initial array is: %s, length is: %d",
chBffr, strlen (chBffr));
fprintf (stdout, "\n NUMELEMS(chBffr) = %d", NUMELEMS (chBffr));
/* __ New Size */
chBffr = expandAr_char (chBffr, itBlxLngth, 2);
fprintf (stdout, "\n New size of char array chBffr is: %d", sizeof
(chBffr));
fprintf (stdout, "\n New size of char array chBffr is: %d", sizeof
(*chBffr));
for (itI = 0; (itI < itBlxLngth); ++itI)
{
chBffr[itI] = (char) (itI + 65);
}
for (itI = 0; (itI < itBlxLngth); ++itI)
{
chBffr[itI + itBlxLngth] = (char) (itI + 97);
}
chBffr[2 * itBlxLngth + 1] = '\0';
fprintf (stdout, "\n Content of expanded array is: %s, length is: %d",
chBffr, strlen (chBffr));
/* ---------------- int array ------------------ */
/* __ Initial Size */
uitFfstDif = (unsigned int *) calloc (itBlxLngth, sizeof (unsigned
int));
fprintf (stdout, "\n\n Size of unsigned int array uitFfstDif is: %d",
sizeof (uitFfstDif));
fprintf (stdout, "\n Size of unsigned int array uitFfstDif is: %d",
sizeof (*uitFfstDif));
for (itI = 0; (itI < itBlxLngth); ++itI)
{
uitFfstDif[itI] = (unsigned int) (itI + 65);
}
fprintf (stdout, "\n Content of initial array is:\n");
for (itI = 0; (itI < itBlxLngth); ++itI)
fprintf (stdout, "(%d,%d) ", itI, uitFfstDif[itI]);
/* fprintf(stdout,"\n
uitFfstDif[%d]=%d",2*itBlxLngth,uitFfstDif[2*itBlxLngth]); // Reading an Off
value */
/* __ New Size */
uitFfstDif = expandAr_uint (uitFfstDif, itBlxLngth, 2);
fprintf (stdout, "\n Size of unsigned int array uitFfstDif is: %d",
sizeof (uitFfstDif));
fprintf (stdout, "\n Size of unsigned int array uitFfstDif is: %d",
sizeof (*uitFfstDif));
for (itI = 0; (itI < itBlxLngth); ++itI)
{
uitFfstDif[itI] = (unsigned int) (itI + 65);
}
for (itI = 0; (itI < itBlxLngth); ++itI)
{
uitFfstDif[itI + itBlxLngth] = (unsigned int) (itI + 97);
}
fprintf (stdout, "\n Content of initial array is:\n");
for (itI = 0; (itI < 2 * itBlxLngth); ++itI)
fprintf (stdout, "(%d,%d) ", itI, uitFfstDif[itI]);
itBlxLngth *= 2;
}
fprintf (stdout, "\n NUMELEMS(chBffr02) = %d", NUMELEMS (chBffr02));
fprintf (stdout, "\n NUMELEMS(uitFfstDif02) = %d", NUMELEMS
(uitFfstDif02));
wait (LblEnd);
LblEnd:;
fprintf (stdout, "\n");
return (0);
}
--
-hs- Tabs out, spaces in.
CLC-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
ISO-C Library: http://www.dinkum.com/htm_cl
FAQ de FCLC : http://www.isty-info.uvsq.fr/~rumeau/fclc
>
> Oops!
>
> Sorry! Newsreaders Problems!
>
> Here is the message again.
>
> -------------------------------
> Hi,
>
> I am trying to get the actual length of a dynamically allocated array.
Thats totally impossible. It's completly on you to save the size of an
moemory object you allocate with malloc if you need that information
yourself.
--
Tschau/Bye
Herbert
--
Member 53 of Team OS/2 Germany
FIDONET : 2:2476/493 LinuxNet: 44:4968/65 OS2Net :
81:497/830
MxBBSNet: 256:4960/345 SOLINET : 49:114/2000 WiPostNet:
777:4918/9090
Mailbox : 49-7273-93072 analog + ISDN
Visit my Homepage: look at: http://www.was-ist-fido.de
http://www.dv-rosenau.de/ home of SQED/32: http://www.sqed.de
OS/2 is the more effective way to utilize your computer.
I think in this case it does more harm than good to phrase your
answer in the terms of the OP. "Dynamically-allocated array" is
a misleading term for the reasons you explained, but you never
explicitly pointed this out.
To the OP: Make sure you get arrays and pointers sorted out.
It's easy to mix the two up at first, but it's a really important
distinction to make.
HTH,
--ag
--
Artie Gold, Austin, TX (finger the cs.utexas.edu account
for more info)
mailto:ag...@bga.com or mailto:ag...@cs.utexas.edu
--
A: Yes I would. But not enough to put it out.
I do not know if this is actually in the ANSI-C specs, but with all
compilers I know the length of a malloc'd piece of memory is in the 4
bytes ahead of the pointer that is returned.
buf = (mytype *) malloc(0xFFFF);
size = *((long *)buf-1);
I know it looks ugly though ...
willem
This is of course not defined by the standard, and not portable at-all.
#include <stdlib.h>
#include <stdio.h>
#define TYPE 1 /* 1 2 3 */
#if TYPE == 1
typedef char type_t;
#endif
#if TYPE == 2
typedef int type_t;
#endif
#if TYPE == 3
typedef long type_t;
#endif
int main (void)
{
type_t *buf = malloc (1234);
if (buf)
{
long size = *((long *) buf - 1);
printf ("size = %ld\n", size);
free (buf);
}
return 0;
}
With type_t = char :
BC 3.1 SMALL :
size = 58590423
BC 3.1 LARGE :
size = -1862336434
DJGPP :
size = 1241
Not very useful... Should I try with TYPE = 2 or 3?
This has of course nothing to do with your TYPE, only with the header
for the allocated and free blocks of the memory pool.
It had always worked for me with the BC large model, but I guess the
size is an unsigned, so 2 bytes for a small model. I also assume the
memory block is aligned, so 1234 will mostly print 1236 for a large
model with DWORD alignment.
willem
Of course I mean 16/32 bits code instead of small/large model.
So try this:
buf = malloc(2000);
size = *((unsigned *)buf-1);
willem
I did.
BC 3.1 SMALL :
size = 894
BC 3.1 LARGE :
size = 37119
DJGPP :
size = 1241
I'm still not conviced...
?? please tell me what the value of the 4 bytes (maybe make it 10) just
ahead of the address returned by malloc is. It works for me with Watcom
9.5 and BCC 5.5, but they only produce 32 code. Maybe the type is
unsigned int, but I'm sure there is a header in this area with the size
of the allocated memory in it.
willem
I have added a marker:
buf[0] = 0x55;
buf[1] = 0xAA;
With BC 3.1 in SMALL mode, the debugger says:
*(buf+0),20m: 55 AA FF FF FF 00 FF FF FF 80 FF FF FF 00 FF FF FF 80 FF FF
*(buf-10),20m: FF FF FF FF FF FF D7 04 7E 03 55 AA FF FF FF 00 FF FF FF 80
buf,p: DS:0586
Note: 1234 in hex is $04D2
We have a $04D7 at -4 and a $037E at -2. Does it help?
This is completely irrelevant. Your technique is non-portable, and
invokes undefined behaviour - you're trying to access memory you don't
own.
--
Richard Heathfield
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
Well, I'm not only trying to access the memory, but I'm also succeeding
in doing so. That's the power of C, isn't it, and you should know as the
25% author of C-unleashed ...
Besides in my K&R copy from '78, the memory pool has been described in
$8.7 and in my experience most compilers just implemented this model as
it had been suggested. So what is really keeping me from defining a
function get_memsize(void *ptr) for my own use, except from some guys
like you who make me feel like I'm doing something highly illegal?
willem
He knows very well that dereferencing (and, in most cases, merely
computing) out-of-bounds pointers invokes undefined behavior. Which
is what he told you.
> Besides in my K&R copy from '78, the memory pool has been described in
> $8.7 and in my experience most compilers just implemented this model as
> it had been suggested.
Your experience is limited. There might or might not be
implementations that work differently; there is no way to tell.
> So what is really keeping me from defining a
> function get_memsize(void *ptr) for my own use, except from some guys
> like you who make me feel like I'm doing something highly illegal?
Consider an architecture that doesn't store a memory block's length
in the word preceding the block.
Consider a segmented architecture where malloc() gives you a memory
block right at the beginning of a segment. Where exactly is the word
that stores the block's length? Is there a word that precedes the
memory block?
Consider that the C language says that a program that attempts to
compute a pointer that doesn't point to an array element or one past
the end of the array invokes undefined behavior.
Consider that, as far as I can tell, you still haven't posted
working code to illustrate your method.
Gergo
--
Mirrors should reflect a little before throwing back images.
-- Jean Cocteau
I would think the fact that it fails (as shown by -hs-; I can give
you more examples of systems on which it fails, if you like) would
suffice to discourage you. :-)
--
In-Real-Life: Chris Torek, Berkeley Software Design Inc
El Cerrito, CA, USA Domain: to...@bsdi.com +1 510 234 3167
http://claw.bsdi.com/torek/ (not always up) I report spam to abuse@.
Nope. It's the power of wishful thinking. You have found a trick which
works for your particular version of your particular compiler for your
particular version of your particular operating system for your
particular hardware, and you are making the mistake of thinking that
what works for you is guaranteed to work for everyone. It ain't
necessarily so. That's why we have an international standard for the
language - so that we know what is guaranteed to work everywhere, and
what isn't. Your technique isn't.
> Besides in my K&R copy from '78, the memory pool has been described in
> $8.7
I don't have the '78 edition (yet!) but I'm guessing its chapter layout
is similar to the '88 edition. If so, please note that Chapter 8 deals
with Unix-specific stuff, and does not claim to be portable.
> and in my experience most compilers just implemented this model as
> it had been suggested.
Most isn't all, and "in my experience" is not the same as "ISO/IEC
9899:1999 guarantees that".
> So what is really keeping me from defining a
> function get_memsize(void *ptr) for my own use,
Nothing. Just don't kid yourself that it's portable.
> except from some guys
> like you who make me feel like I'm doing something highly illegal?
Depends what you mean by "illegal". It probably won't bring the police
to your door at 3am, if that's what you mean. From a language point of
view, though, I think it falls into that category. It's actually
undefined behaviour.
From 6.5.6 of ISO/IEC 9899:1999:
"When two pointers are subtracted, both shall point to elements of the
same array object, or one past the last element of the array object; the
result is the difference of the subscripts of the two array elements."
From 4 (Conformance) of the same document:
"In this International Standard, 荘shall鋳 is to be interpreted as a
requirement on an implementation or on a program; conversely, 荘shall
not鋳 is to be interpreted as a prohibition. 2 If a 荘shall鋳 or 荘shall
not鋳 requirement that appears outside of a constraint is violated, the
behavior is undefined."
3.4.3 (undefined behavior):
"behavior, upon use of a nonportable or erroneous program construct or
of erroneous data, for which this International Standard imposes no
requirements"
In other words, if your technique is used, the implementation is allowed
to do anything. Your attempt to capture size information on dynamically
allocated memory is a weakness in your program which gives your
implementation licence to destroy the world, if you happen to have the
right hardware options connected.
I did not suggest it works for everyone. It indeed works under the
particular conditions you mention, but that happens to be a quite
commonly used combination of hard- and software.
So whenever I do *((long*)buf-1) I get the size of the allocated memory
with the 32 bits flat model compilers I use under NT. And that info can
be useful if you try to debug buffer overflows ..
> That's why we have an international standard for the language - so
> that we know what is guaranteed to work everywhere, and what isn't.
> Your technique isn't.
Again, it is not my primary concern that everything will work
everywhere. In that's what you want, go Java.
> I don't have the '78 edition (yet!) but I'm guessing its chapter
> layout is similar to the '88 edition. If so, please note that Chapter
> 8 deals with Unix-specific stuff, and does not claim to be portable.
There is no date in my copy, only the '78 copyright by Bell.
But chapter 8 is indeed about the Unix system interface and it also
includes the example of a storage allocator. Could it be that some
compilers implemented memory allocation as it has been suggested here?
[snip]
> In other words, if your technique is used, the implementation is
> allowed to do anything. Your attempt to capture size information on
> dynamically allocated memory is a weakness in your program which
> gives your implementation licence to destroy the world, if you happen
> to have the right hardware options connected.
I think you are overconcerned about software destroying the world ...
No, I do not use this size info in my programs, however I do use it for
debugging. But I do not quite understand why there isn't a function in
common C that returns the size of allocated memory. That would at least
make it possible to solve my output buffer problems in a more general
way. And whether it is in memory that I am allowed to read or not, the
information to do that is there somewhere, isn't it?
willem
Then it's off-topic here.
<snip>
<snip>
>I did not suggest it works for everyone. It indeed works under the
>particular conditions you mention, but that happens to be a quite
>commonly used combination of hard- and software.
Don't be too sure of that. I think that the 8051 chip I'm currently
developing for is much more common (or at least it will be when I'm
done :-) ).
<snip>
>There is no date in my copy, only the '78 copyright by Bell.
>But chapter 8 is indeed about the Unix system interface and it also
>includes the example of a storage allocator. Could it be that some
>compilers implemented memory allocation as it has been suggested here?
I woould reverse that question:
Is it possible that some compiler developer did NOT follow the
suggestion of K&R?
If you can't prove the answer must be no, then you should not
recommend your non-portable trick without stating that it is
non-portable and for which platforms/compilers it works and doesn't
work.
>
>[snip]
>
>Richard Heathfield wrote:
>>
>> In other words, if your technique is used, the implementation is
>> allowed to do anything. Your attempt to capture size information on
>> dynamically allocated memory is a weakness in your program which
>> gives your implementation licence to destroy the world, if you happen
>> to have the right hardware options connected.
>
>I think you are overconcerned about software destroying the world ...
>No, I do not use this size info in my programs, however I do use it for
>debugging. But I do not quite understand why there isn't a function in
>common C that returns the size of allocated memory. That would at least
>make it possible to solve my output buffer problems in a more general
>way. And whether it is in memory that I am allowed to read or not, the
>information to do that is there somewhere, isn't it?
No, the size information is not nessesarily available. I can easily
build a *alloc/free implementation that does not keep a record of the
size of the blocks. I would simply ignore the size argument, and give
you a block of fixed size.
(And if i find later I have to keep track of the size after all, i
would do that in the number of blocks I gave out, not in bytes)
>
>willem
Bart v Ingen Schenau
--
Remove NOSPAM to mail me directly
FAQ for clc: http://www.eskimo.com/~scs/C-faq/top.html
All this sounds very interesting, but please tell me what would be the
benefit from building a storage allocator that does not keep track of
the amount of memory allocated. Of course I can also build one that
ignores the size argument, but that does not seem very practical to me.
And if the size is not actually stored somewhere, it's always available
implicitly by substracting the current address from the next block
pointer.
willem
<snip>
> And if the size is not actually stored somewhere, it's always available
> implicitly by substracting the current address from the next block
> pointer.
No, because they would be pointers to different objects, so you can't
subtract one from the other (at least, if you do, the result is
undefined).
Exception: if you allocated one huge block yourself, and are dishing it
out yourself in chunks, that would be all right...
>"B. van Ingen Schenau" wrote:
>>
>> <wil...@veenhoven.com> wrote:
>>
>> >[snip] But I do not quite understand why there isn't a function in
>> >common C that returns the size of allocated memory. That would at
>> >least make it possible to solve my output buffer problems in a more
>> >general way. And whether it is in memory that I am allowed to read
>> >or not, the information to do that is there somewhere, isn't it?
>>
>> No, the size information is not nessesarily available. I can easily
>> build a *alloc/free implementation that does not keep a record of the
>> size of the blocks. I would simply ignore the size argument, and give
>> you a block of fixed size.
>>
>> (And if i find later I have to keep track of the size after all, i
>> would do that in the number of blocks I gave out, not in bytes)
>
>All this sounds very interesting, but please tell me what would be the
>benefit from building a storage allocator that does not keep track of
>the amount of memory allocated. Of course I can also build one that
>ignores the size argument, but that does not seem very practical to me.
I don't care if you think it practical or not. The fact is that it can
be done.
In fact, I happen to have one on my DS 9000, and I didn't even make
that one myself.
>And if the size is not actually stored somewhere, it's always available
>implicitly by substracting the current address from the next block
>pointer.
Even if my allocator does not use linear addressing, and selects
blocks to dole out randomly?
And many existing allocators maintain a pool of freed block, that they
will re-use when a request for an appropriately sized block comes.
Even is an allocator does not give ouyt block randomly, the blocks
will most certainly not consecutive.
Ever since Byte suddenly died I feel like I'm missing out on all this
exiting technology. What is a DS 9000?
> >And if the size is not actually stored somewhere, it's always
> >available implicitly by substracting the current address from the
> >next block pointer.
>
> Even if my allocator does not use linear addressing, and selects
> blocks to dole out randomly?
That's another thing that kept me awake last night: How do you free a
block if it is handed out randomly and you do not know the size of it?
> And many existing allocators maintain a pool of freed block, that
> they will re-use when a request for an appropriately sized block
> comes.
Sounds familiar. But at least in this situation the size is known ...
> Even is an allocator does not give out block randomly, the blocks
> will most certainly not consecutive.
No, but in most cases there is at least some record of sizes, either by
pointer arithmetic, or in any other way. Thus far your examples did not
convince me.
willem
> Ever since Byte suddenly died I feel like I'm missing out on all this
> exiting technology. What is a DS 9000?
The DeathStation 9000 is a special computer, including the feature
that ANY undefined behaviour causes a crash, or even worse results.
--
/-- Joona Palaste (pal...@cc.helsinki.fi) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #80 D+ ADA N+++ |
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"Stronger, no. More seductive, cunning, crunchier the Dark Side is."
- Mika P. Nieminen
> Ever since Byte suddenly died I feel like I'm missing out on all this
> exiting technology. What is a DS 9000?
First, the good news, it doesn't really exist.
DS9000 (or DS9k) is short for the "Death Station 9000". It is a
computer famous for it's pedantically compliant C implementation.
For example...
When space for an array is allocated, a demon lord is placed one byte
past the end. That demon doesn't mind being pointed to, but try and
access it, it will be offended and bad things will happen.
Also, the demons that perform variable modification are rather
rowdy, and not at all team players. Send two off to modify the same
area of memory between sequence points (i=i++) and they start
fighting.
This is all allowed according to the C standard. Undefined behaviour.
It's not all bad though. I once called clrscr(), and I had a momentary
vision of total clarity.
Anyway, the point of the DS9k in this ng is to remind people of the
liberties a C implementation can take.
Bill, has a talking keyboard.
| > except from some guys
| > like you who make me feel like I'm doing something highly illegal?
|
| Depends what you mean by "illegal". It probably won't bring the police
| to your door at 3am, if that's what you mean.
It might even do that if the computer is hooked up to a modem connected to
the phone line.
--Daniel
--
"The obvious mathematical breakthrough would be development of an easy
way to factor large prime numbers." -- Bill Gates, "The Road Ahead"
> Ever since Byte suddenly died I feel like I'm missing out on all this
> exiting technology. What is a DS 9000?
Besides the following, there was a wonderful webpage on the
DS/9000 designed by Heathfield (et al?). I don't know whether it
is still up, though.
Sender: blp@pfaffben
Newsgroups: comp.lang.c
Subject: Welcome to DeathSoft
Reply-To: pfaf...@pilot.msu.edu
BCC: pfaf...@pilot.msu.edu
From: Ben Pfaff <pfaf...@pilot.msu.edu>
Date: 12 Dec 1998 10:34:13 -0500
Message-ID: <87d85pi...@dial1.msu.edu>
Lines: 61
X-Newsreader: Gnus v5.5/Emacs 20.3
--text follows this line--
Welcome to DeathSoft
(an original work of fantasy)
by Ben Pfaff
Here at DeathSoft we write a lot of ANSI C code. We have to if we
want our leading product, DeathWorks, to retain it rank as the most
popular all-ANSI C office suite. Of course, this doesn't come easy.
ANSI C conformance is difficult to ensure even in small programs, and
in something as large as DeathWorks, it was almost impossible.
That's why, a few years ago, we developed the DeathStation and the
DeathC compiler. We use them to develop all our software now, because
we know it's ``write once, run anywhere,'' with only a recompile
needed for each new platform.
The most unique aspect of writing C on the DeathStation is what occurs
when undefined behavior is invoked, at compile time or runtime.
Before the DeathStation, to speak of undefined behavior ``making
demons shoot out of one's nose'' was purely figurative. But on a
DeathStation, nasal demons are only one of a host of olfactory
apparitions included standard. They're not even the nastiest,
although having tiny pitchforks stabbed into the interior of your nose
is not a good feeling at any time.
(If you thought that GNU C sometimes behaved strangely when you fed it
a #pragma or two, you should see what DeathC does! Or, rather, *feel*
it...)
DeathC also takes a liberal (if rather high-voltage) interpretation of
what constitutes a `compiler diagnostic'. Such things as v?id main()
are treated severely, and it's best not to mention them even in a
non-C context on the DeathStation.
As a result of all this, our programmers are among the most nervous in
the industry. They're also some of the most careful. We do, however,
require them to sign a tortuous collection of disclaimers before even
coming near one of the DeathStations.
We do tend to have high staff turnover here at DeathSoft; if you'd
like to work for us, just send me an email and I'd be glad to look
over your resume. Just so you don't get a nasty surprise, you might
want to check over some of your existing code with DeathLint before
considering applying.
The DeathStation itself is available in two models, 1000 and 9000.
DeathStation 1000 was our first attempt, which we designed in the
strict spirit of the ANSI C standard. It consisted of a keyboard
labeled `stdin' attached to a typewriter labeled `stdout'.
Unfortunately some users complained, so we designed the 9000, a
keyboard labeled `stdin' attached to a 25" Trinitron screen with
2048x2048 resolution labeled `stdout'. Some have suggested that model
9000 suffers from second-system effect, but we like it.
Of course, since the 1000 and 9000 are developer machines, they're
both quad-processor 600 MHz Alphas cooled to -40 degrees and
overclocked to 750 MHz.
--
"I ran it on my DeathStation 9000 and demons flew out of my nose." --Kaz
Please: do not email me copies of your posts to comp.lang.c
do not ask me C questions via email; post them instead
--
"Give me a couple of years and a large research grant,
and I'll give you a receipt." --Richard Heathfield
I think it was this one:
http://www.gfd34.dial.pipex.com/art
I hit it with lynx to see if it was still up and it seems to be, though
I didn't follow any of the links to real text to make sure it was the
right one.
>--text follows this line--
>Welcome to DeathSoft
>(an original work of fantasy)
>by Ben Pfaff
(...)
>We do tend to have high staff turnover here at DeathSoft; if you'd
>like to work for us, just send me an email and I'd be glad to look
>over your resume. Just so you don't get a nasty surprise, you might
>want to check over some of your existing code with DeathLint before
>considering applying.
Are they hiring students for part-time jobs in Waterloo? It's that
time of the term again...
dave
--
Dave Vandervies dj3v...@student.math.uwaterloo.ca
> Oh how I hate the McVoidmain's! Almost as much as the MacAstmallocs.
Oh dear. I can't help thinking the OP has a point. :-) --Mark A. Odell and
Richard Heathfield comment on CLC being called `a bunch of sad tossers'
It's still up? Cool. That was Bryan W and me, yes. We worked it so that
Bryan asked the question "What is the DS9K?" (this was last April 1,
obviously; in fact, in the USA it would still have been March 31 - we
were working to BST, naturally), and I would answer with this URL. Nice
and simple, only in the few brief seconds between Bryan posting the
question and my posting the URL, at least two other people had managed
to answer him, one of whom was Ben, with his skit on the DS9K -
basically the same idea as ours, although a different way of carrying it
out.
I still can't get over that photo of Kaz. :-)
>"B. van Ingen Schenau" wrote:
>>
>> On Tue, 02 Jan 2001 21:25:39 +0100, willem veenhoven
>> <wil...@veenhoven.com> wrote:
>>
<snip>
>> >And if the size is not actually stored somewhere, it's always
>> >available implicitly by substracting the current address from the
>> >next block pointer.
>>
>> Even if my allocator does not use linear addressing, and selects
>> blocks to dole out randomly?
>
>That's another thing that kept me awake last night: How do you free a
>block if it is handed out randomly and you do not know the size of it?
But I do know the size. It's this magic number right here in the
middle of the code. Too bad it can't be used by anyone else ;-)
And you give me the address of the block to free, so what's the
problem with handing blocks out in a random order?
>
>> And many existing allocators maintain a pool of freed block, that
>> they will re-use when a request for an appropriately sized block
>> comes.
>
>Sounds familiar. But at least in this situation the size is known ...
Who says the size is unknown to the allocation functions. We are just
tryint to make clear that there are more possibilities to keep track
of the size besides a byte-count just before the actual block.
>
>> Even is an allocator does not give out block randomly, the blocks
>> will most certainly not consecutive.
>
>No, but in most cases there is at least some record of sizes, either by
>pointer arithmetic, or in any other way. Thus far your examples did not
>convince me.
So you have taken a peek in forbidden territory, and found out how
many blocks I gave you. Do you now have enough information to
determine the size of those blocks?
Remember that I am at liberty to give you more memory than you
requested.
Let's assume I use blocks of 1234 bytes, and you requested 2468 bytes.
To satisfy your request I can give you 2, 3, 4 or even more
consecutive blocks of memory, and I do not need to be consistent with
that.