By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,132 Members | 1,267 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,132 IT Pros & Developers. It's quick & easy.

Need to find size of destination buffer for strncpy

P: n/a
Hi all,
We are using strcpy to copy strings in our app. This gave us problems
when the destination buffer is not large enough. As a workaround, we
wanted to replace calls to strcpy with strncpy. That is, replace calls
to strcpy with say, my_strcpy(dest,src) which will internally find the
destination buffer length.

For this we need to know the destination buffer size. For statically
allocated strings sizeof is returning the length of the array
correctly, but not for malloced strings (char*). Hence we are not able
to replace calls to strcpy with strncpy with appropriate length
parameter.

Is there any other way out? Changing all the static and dynamic
allocations in the application is very very difficult (around 15k
instances will have to be changed).

Regards,
Frodo

Dec 28 '06 #1
Share this Question
Share on Google+
43 Replies


P: n/a
On Wed, 27 Dec 2006 23:09:48 -0600, Frodo Baggins wrote
(in article <11**********************@n51g2000cwc.googlegroups .com>):
Hi all,
We are using strcpy to copy strings in our app. This gave us problems
when the destination buffer is not large enough. As a workaround, we
wanted to replace calls to strcpy with strncpy. That is, replace calls
to strcpy with say, my_strcpy(dest,src) which will internally find the
destination buffer length.

For this we need to know the destination buffer size. For statically
allocated strings sizeof is returning the length of the array
correctly, but not for malloced strings (char*). Hence we are not able
to replace calls to strcpy with strncpy with appropriate length
parameter.
$ man strlen
--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw

Dec 28 '06 #2

P: n/a

Randy Howard wrote:
On Wed, 27 Dec 2006 23:09:48 -0600, Frodo Baggins wrote
(in article <11**********************@n51g2000cwc.googlegroups .com>):
Hi all,
We are using strcpy to copy strings in our app. This gave us problems
when the destination buffer is not large enough. As a workaround, we
wanted to replace calls to strcpy with strncpy. That is, replace calls
to strcpy with say, my_strcpy(dest,src) which will internally find the
destination buffer length.

For this we need to know the destination buffer size. For statically
allocated strings sizeof is returning the length of the array
correctly, but not for malloced strings (char*). Hence we are not able
to replace calls to strcpy with strncpy with appropriate length
parameter.

$ man strlen
Seems to me that might be helpful for the source buffer size. How is
it going to help with the destination buffer size?

To the OP:
C does not have real arrays for character strings. They do not know
their own length and there is no simple and reliable way to determine
it. You are just going to have to memorize it yourself with a hash map
or something for those strings that are dynamically allocated.
--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw
Dec 28 '06 #3

P: n/a

"Frodo Baggins" <fr*********@gmail.comwrote in message
news:11**********************@n51g2000cwc.googlegr oups.com...
Hi all,
We are using strcpy to copy strings in our app. This gave us problems
when the destination buffer is not large enough. As a workaround, we
wanted to replace calls to strcpy with strncpy. That is, replace calls
to strcpy with say, my_strcpy(dest,src) which will internally find the
destination buffer length.

For this we need to know the destination buffer size. For statically
allocated strings sizeof is returning the length of the array
correctly, but not for malloced strings (char*). Hence we are not able
to replace calls to strcpy with strncpy with appropriate length
parameter.

Is there any other way out? Changing all the static and dynamic
allocations in the application is very very difficult (around 15k
instances will have to be changed).
The only way for your program to know how much memory was allocated
dynamically is for you to have it 'remember' it (the argument passed
to 'malloc()'. This would much more feasible if you used macros to
define your allocation sizes.

-Mike
Dec 28 '06 #4

P: n/a

"Randy Howard" <ra*********@FOOverizonBAR.netwrote in message
news:00*****************************@news.verizon. net...
On Wed, 27 Dec 2006 23:09:48 -0600, Frodo Baggins wrote
(in article <11**********************@n51g2000cwc.googlegroups .com>):
>Hi all,
We are using strcpy to copy strings in our app. This gave us problems
when the destination buffer is not large enough. As a workaround, we
wanted to replace calls to strcpy with strncpy. That is, replace calls
to strcpy with say, my_strcpy(dest,src) which will internally find the
destination buffer length.

For this we need to know the destination buffer size. For statically
allocated strings sizeof is returning the length of the array
correctly, but not for malloced strings (char*). Hence we are not able
to replace calls to strcpy with strncpy with appropriate length
parameter.

$ man strlen
How will 'strlen()' help? He's asking about buffers, not strings.

-Mike
Dec 28 '06 #5

P: n/a
# On Wed, 27 Dec 2006 23:09:48 -0600, Frodo Baggins wrote
# For this we need to know the destination buffer size. For statically
# allocated strings sizeof is returning the length of the array
# correctly, but not for malloced strings (char*). Hence we are not able
# to replace calls to strcpy with strncpy with appropriate length
# parameter.

Some systems provide a call on a mallocked pointer that gives
a size either of the original malloc or the allocated space
which may be a little bigger. If you have that available, you
can do that in a system dependent manner.

You can also use a malloc wrapper that records the block size with
the block. Otherwise, because of what C is, you're screwed.

Note that for
void a(void) {
...
char z[M];
...
b(z);
...
}
void b(char *x) {
...
you don't have access to M here
unless you provide an explicit way
such as additional parameter to b(z,M).
...
}

--
SM Ryan http://www.rawbw.com/~wyrmwif/
Elvis was an artist. But that didn't stop him from joining the service
in time of war. That's why he is the king, and you're a shmuck.
Dec 28 '06 #6

P: n/a
Frodo Baggins wrote:
>
We are using strcpy to copy strings in our app. This gave us problems
when the destination buffer is not large enough. As a workaround, we
wanted to replace calls to strcpy with strncpy. That is, replace calls
to strcpy with say, my_strcpy(dest,src) which will internally find the
destination buffer length.

For this we need to know the destination buffer size. For statically
allocated strings sizeof is returning the length of the array
correctly, but not for malloced strings (char*). Hence we are not able
to replace calls to strcpy with strncpy with appropriate length
parameter.

Is there any other way out? Changing all the static and dynamic
allocations in the application is very very difficult (around 15k
instances will have to be changed).
Don't use strncpy - it has some very awkward properties. Use
strlcpy. (See <http://cbfalconer.home.att.net/download/>

Assuming you have malloced the string storage areas to fit the
strings with "field = malloc(strlen(src) + 1);" strlen(field) will
yield the right length. If that is too small you can realloc
before revising field. Otherwise, just remember what you
malloced. You have to know which instances of field are static,
local, or malloced anyhow.

It sounds as if your code is highly disorganized if this is a
problem. Good luck, you'll need it.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

Dec 28 '06 #7

P: n/a
Frodo Baggins a écrit :
Hi all,
We are using strcpy to copy strings in our app. This gave us problems
when the destination buffer is not large enough. As a workaround, we
wanted to replace calls to strcpy with strncpy. That is, replace calls
to strcpy with say, my_strcpy(dest,src) which will internally find the
destination buffer length.

For this we need to know the destination buffer size. For statically
allocated strings sizeof is returning the length of the array
correctly, but not for malloced strings (char*). Hence we are not able
to replace calls to strcpy with strncpy with appropriate length
parameter.

Is there any other way out? Changing all the static and dynamic
allocations in the application is very very difficult (around 15k
instances will have to be changed).

Regards,
Frodo
Replace all your malloc calls with this two functions.
They will allow you to know immediately the size of an
allocated object, besides giving you more security in handling
pointers, since they can give you a hint if the passed
pointer really points to an allocated buffer.
-------------------------------------------------------------cut here
/* this will be written at the end of the allocated block.
If this is overwritten it means something has written
beyond the block */
#define MAGIC 0xFFFF
/* This signature will be written at the start of the
allocated block to avoid freeing memory that wasn't
allocated at all */
#define SIGNATURE 12345678L
/* This variable counts the size of the memory allocated
so far. This is useful for detecting memory leaks */
static long AllocatedMemory;
/* This allocates a block, writing the signature, then
the size of the block. The useful data starts after
those two ints. At the end of the block, the "MAGIC"
number is written to detect overwrites */
void *allocate(int size)
{
register char *r;
register int *ip = NULL;

if (size <= 0)
return NULL;
size += 3 * sizeof(int);
r = malloc((size_t)size);
if (r == NULL)
return NULL;
memset(r, 0, (size_t) size);
AllocatedMemory += size;
ip = (int *) r;
*ip++ = SIGNATURE;
*ip++ = size;
memset(ip, 0, size - 3*sizeof(int));
ip = (int *) (&r[size - sizeof(int)]);
*ip = MAGIC;
return (r + 2 * sizeof(int));
}
/*
This releases a block verifying that it wasn't overwritten
and that it is really a block. It will not free a block
that doesn't fulfill those characteristics.
*/
void release(void *pp)
{
register int *ip = NULL;
int s;
register char *p = pp;
if (p == NULL)
return;
p -= 2 * sizeof(int);
ip = (int *) p;
if (*ip == SIGNATURE) {
*ip++ = 0;
s = *ip;
ip = (int *) (&p[s - sizeof(int)]);
if (*ip != MAGIC) {
fprintf(stderr,"overwritten block size %d\n",s);
}
*ip = 0;
AllocatedMemory -= s;
free(p);
}
else {
fprintf(stderr,"Wrong block passed to release\n");
}
}

/* This will return the size of a block or -1 if it is not
a valid block
*/
int GetSize(void *block)
{
int *ip = block;

ip -= 2;
if (*ip != SIGNATURE)
return -1;
ip++;
return *ip;
}
Dec 28 '06 #8

P: n/a
CBFalconer said:

<snip>
>
Don't use strncpy - it has some very awkward properties. Use
strlcpy.
Please don't recommend non-standard functions without at least pointing out
that they will render the code non-portable. Thank you.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 28 '06 #9

P: n/a
Frodo Baggins said:
Hi all,
We are using strcpy to copy strings in our app.
Fine.
This gave us problems when the destination buffer is not large enough.
No, strcpy was not the cause of these problems. The cause of these problems
was that the destination buffer is not large enough. The solution is to
make the destination buffer large enough.
As a workaround, we
wanted to replace calls to strcpy with strncpy.
That's a good way to throw away data. It can also be a good way to lose your
null termination if you're not careful.
That is, replace calls
to strcpy with say, my_strcpy(dest,src) which will internally find the
destination buffer length.
When you create the buffer, you know how big it is. Don't Forget.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 28 '06 #10

P: n/a
On Thu, 28 Dec 2006 10:25:12 +0000, in comp.lang.c , Richard
Heathfield <rj*@see.sig.invalidwrote:
>CBFalconer said:

<snip>
>>
Don't use strncpy - it has some very awkward properties. Use
strlcpy.

Please don't recommend non-standard functions
He didn't - he recommended using some code of his own which is
portable across different implementations.
>without at least pointing out that they will render the code non-portable.
I suggest you read the code before making assumptions. :-)
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Dec 28 '06 #11

P: n/a
Mark McIntyre said:
On Thu, 28 Dec 2006 10:25:12 +0000, in comp.lang.c , Richard
Heathfield <rj*@see.sig.invalidwrote:
>>CBFalconer said:

<snip>
>>>
Don't use strncpy - it has some very awkward properties. Use
strlcpy.

Please don't recommend non-standard functions

He didn't - he recommended using some code of his own which is
portable across different implementations.
Since it invades implementation namespace, I disagree. On the other hand,
since Chuck has a clue or two to spare, he has taken the trouble to
document the fact, so please don't feel I'm getting on his case.

Incidentally, under C90 rules, he also makes a non-portable assumption about
the meaning of the implementation-reserved identifier __cplusplus. This is
not an unreasonable assumption. Nevertheless, strictly speaking, it is
non-portable.

(Finally, in his test driver I would recommend using const for str1 on line
100 and for s2 on line 84, although these are not, strictly speaking,
portability issues.)

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 28 '06 #12

P: n/a
Richard Heathfield a écrit :
Mark McIntyre said:

>>On Thu, 28 Dec 2006 10:25:12 +0000, in comp.lang.c , Richard
Heathfield <rj*@see.sig.invalidwrote:

>>>CBFalconer said:

<snip>

Don't use strncpy - it has some very awkward properties. Use
strlcpy.

Please don't recommend non-standard functions

He didn't - he recommended using some code of his own which is
portable across different implementations.


Since it invades implementation namespace, I disagree.
look heathfield, if the strlcpy function is already defined
in some implementation there is no need for Chuck's version
probably. The porting has been done ALREADY!!!

Your argument is nonsense.
On the other hand,
since Chuck has a clue or two to spare, he has taken the trouble to
document the fact, so please don't feel I'm getting on his case.
You do.
Incidentally, under C90 rules, he also makes a non-portable assumption about
the meaning of the implementation-reserved identifier __cplusplus. This is
not an unreasonable assumption. Nevertheless, strictly speaking, it is
non-portable.
Please tell me a single implementation that uses the identifier
__cplusplus
for another reason than what everyone uses it for!!!

This is, again, pure heathfield.
Dec 28 '06 #13

P: n/a
jacob navia said:
Richard Heathfield a écrit :
>Mark McIntyre said:
>>>On Thu, 28 Dec 2006 10:25:12 +0000, in comp.lang.c , Richard
Heathfield <rj*@see.sig.invalidwrote:
CBFalconer said:
<snip>
>Don't use strncpy - it has some very awkward properties. Use
>strlcpy.

Please don't recommend non-standard functions

He didn't - he recommended using some code of his own which is
portable across different implementations.

Since it invades implementation namespace, I disagree.

look heathfield, if the strlcpy function is already defined
in some implementation there is no need for Chuck's version
probably. The porting has been done ALREADY!!!
Since there is no ISO C definition of strlcpy, there is no obligation on any
implementor to avoid implementing strlcpy with completely different
semantics to Chuck's version.
Your argument is nonsense.
No, it isn't. Think it through all the way instead of shooting from the hip
all the time.

<snip>
>Incidentally, under C90 rules, he also makes a non-portable assumption
about the meaning of the implementation-reserved identifier __cplusplus.
This is not an unreasonable assumption. Nevertheless, strictly speaking,
it is non-portable.

Please tell me a single implementation that uses the identifier
__cplusplus
for another reason than what everyone uses it for!!!
I don't know of any (which is why I said it's not an unreasonable
assumption), but absence of evidence is not evidence of absence (which is
why I said it's, strictly speaking, non-portable).
This is, again, pure heathfield.
Yes - it's correct and potentially useful information.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 28 '06 #14

P: n/a
Richard Heathfield wrote:
CBFalconer said:

<snip>
>>
Don't use strncpy - it has some very awkward properties. Use
strlcpy.

Please don't recommend non-standard functions without at least
pointing out that they will render the code non-portable. Thank you.
That is pointed out in the <snippedpackage I recommended. Since
the package is in source format, and uses only standard C, the
actuality is that it is portable. The only non-portability is the
name.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Dec 28 '06 #15

P: n/a
Richard Heathfield wrote:
jacob navia said:
Richard Heathfield a écrit :
Mark McIntyre said:
On Thu, 28 Dec 2006 10:25:12 +0000, in comp.lang.c , Richard
Heathfield <rj*@see.sig.invalidwrote:
CBFalconer said:
<snip>
Don't use strncpy - it has some very awkward properties. Use
strlcpy.

Please don't recommend non-standard functions

He didn't - he recommended using some code of his own which is
portable across different implementations.

Since it invades implementation namespace, I disagree.
Incidentally, under C90 rules, he also makes a non-portable assumption
about the meaning of the implementation-reserved identifier __cplusplus.
This is not an unreasonable assumption. Nevertheless, strictly speaking,
it is non-portable.
Please tell me a single implementation that uses the identifier
__cplusplus
for another reason than what everyone uses it for!!!

I don't know of any (which is why I said it's not an unreasonable
assumption), but absence of evidence is not evidence of absence (which is
why I said it's, strictly speaking, non-portable).
Checking for a C++ compiler using the __cplusplus macro may not be
strictly conforming in C90, but I believe it is currently 100%
portable. It is possible someone will write a malicious C compiler in
the future, but I would be extremely surprised if such a compiler
exists already, because if it did, I would expect it would be common
knowledge on this newsgroup already. Similarly, __STDC_VERSION__ cannot
be used if you wish to keep your code strictly conforming C90, but I
can't remember seeing any objections to it for that reason in this
newsgroup.

Dec 28 '06 #16

P: n/a
On Thu, 28 Dec 2006 14:09:54 +0100, in comp.lang.c , jacob navia
<ja***@jacob.remcomp.frwrote:
>Richard Heathfield a écrit :
>Since it invades implementation namespace, I disagree.

look heathfield, if the strlcpy function is already defined
in some implementation there is no need for Chuck's version
probably. The porting has been done ALREADY!!!
The standard does say that functions beginning str... are reserved.
Your point has some merit of course.
>Your argument is nonsense.
The argument is based on the C standard. Myself personally, I suspect
RJH overstated his case in his original post and is covering his
tracks a little now, but I forgive him.
>Please tell me a single implementation that uses the identifier
__cplusplus
for another reason than what everyone uses it for!!!
Again, strictly speaking this is irrelevant. Its also post-facto - the
C99 standard codifies this use precisely because everyone began to use
it. That doesn't make it valid C90.
>This is, again, pure heathfield.
You're a tit, you know that don't you?
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Dec 28 '06 #17

P: n/a
Harald van D?k said:

<snip>
Similarly, __STDC_VERSION__ cannot
be used if you wish to keep your code strictly conforming C90, but I
can't remember seeing any objections to it for that reason in this
newsgroup.
Actually, that issue does crop up from time to time.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 28 '06 #18

P: n/a
Harald van D?k wrote:
>
.... snip ...
>
Checking for a C++ compiler using the __cplusplus macro may not be
strictly conforming in C90, but I believe it is currently 100%
portable. It is possible someone will write a malicious C compiler in
the future, but I would be extremely surprised if such a compiler
exists already, because if it did, I would expect it would be common
knowledge on this newsgroup already. Similarly, __STDC_VERSION__ cannot
be used if you wish to keep your code strictly conforming C90, but I
can't remember seeing any objections to it for that reason in this
newsgroup.
#if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)

The value of an undefined id is 0.

--
Merry Christmas, Happy Hanukah, Happy New Year
Joyeux Noel, Bonne Annee.
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>

Dec 28 '06 #19

P: n/a
CBFalconer wrote:
Harald van D?k wrote:
... snip ...

Checking for a C++ compiler using the __cplusplus macro may not be
strictly conforming in C90, but I believe it is currently 100%
portable. It is possible someone will write a malicious C compiler in
the future, but I would be extremely surprised if such a compiler
exists already, because if it did, I would expect it would be common
knowledge on this newsgroup already. Similarly, __STDC_VERSION__ cannot
be used if you wish to keep your code strictly conforming C90, but I
can't remember seeing any objections to it for that reason in this
newsgroup.

#if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)

The value of an undefined id is 0.
A malicious C90 implementation can define __STDC_VERSION__ to 99999999.

Dec 28 '06 #20

P: n/a
jacob navia wrote:
Replace all your malloc calls with this two functions.
They will allow you to know immediately the size of an
allocated object, besides giving you more security in handling
pointers, since they can give you a hint if the passed
pointer really points to an allocated buffer.
-------------------------------------------------------------cut here
/* this will be written at the end of the allocated block.
If this is overwritten it means something has written
beyond the block */
#define MAGIC 0xFFFF
/* This signature will be written at the start of the
allocated block to avoid freeing memory that wasn't
allocated at all */
#define SIGNATURE 12345678L
/* This variable counts the size of the memory allocated
so far. This is useful for detecting memory leaks */
static long AllocatedMemory;
/* This allocates a block, writing the signature, then
the size of the block. The useful data starts after
those two ints. At the end of the block, the "MAGIC"
number is written to detect overwrites */
void *allocate(int size)
This function should take a size_t value as argument. Many systems have
smaller int than size_t, and this unnecessarily restricts what can be
allocated. For example most 64-bit systems have 32-bit int and 64-bit
size_t.
{
register char *r;
register int *ip = NULL;

if (size <= 0)
return NULL;
size += 3 * sizeof(int);
r = malloc((size_t)size);
if (r == NULL)
return NULL;
memset(r, 0, (size_t) size);
AllocatedMemory += size;
ip = (int *) r;
*ip++ = SIGNATURE;
On an implementation with int less than 32 bits, you just mangled your
signature. According to the C99 standard, when converting integer values
to a type in which the value is not representable: "either the result is
implementation-defined or an implementation-defined signal is raised".
*ip++ = size;
If you took my advice to make size a size_t object, then the same
problem applies here: you're forcing it into an int.
memset(ip, 0, size - 3*sizeof(int));
ip = (int *) (&r[size - sizeof(int)]);
*ip = MAGIC;
If size was not a multiple of sizeof(int) then this will be an unaligned
access. Such accesses will trap on many implementations. For example, on
the Sun SPARC architecture.

In addition, if int is 16 bits then 0xFFFF is outside the range of
signed int, and the implementation-defined result or signal referred to
above may occur.
return (r + 2 * sizeof(int));
It's possible that 2*sizeof(int) is not sufficient alignment for some
larger types. For example, if sizeof(int) is 2 but sizeof(long long) is
8 and long long requires 8-byte alignment then one will not be able to
store long longs into this block. Also, if sizeof(int) is 4 but
sizeof(long double) is 16 and requires 16-byte alignment then one will
not be able to store long doubles into this block.
}
[...]
/* This will return the size of a block or -1 if it is not
a valid block
*/
int GetSize(void *block)
{
int *ip = block;

ip -= 2;
if (*ip != SIGNATURE)
return -1;
ip++;
return *ip;
}
If it is not a valid block as allocated by the allocate function above,
then trying to read two ints before the pointed-to location will
probably go outside of the object pointed to. This is of course
undefined behaviour, and may result in a segmentation fault.

--
Simon.
Dec 29 '06 #21

P: n/a
Simon Biber wrote:
jacob navia wrote:
>Replace all your malloc calls with this two functions.
They will allow you to know immediately the size of an
allocated object, besides giving you more security in handling
pointers, since they can give you a hint if the passed
pointer really points to an allocated buffer.
------------------------------------------------------cut here
/* this will be written at the end of the allocated block.
If this is overwritten it means something has written
beyond the block */
#define MAGIC 0xFFFF
/* This signature will be written at the start of the
allocated block to avoid freeing memory that wasn't
allocated at all */
#define SIGNATURE 12345678L
/* This variable counts the size of the memory allocated
so far. This is useful for detecting memory leaks */
static long AllocatedMemory;
/* This allocates a block, writing the signature, then
the size of the block. The useful data starts after
those two ints. At the end of the block, the "MAGIC"
number is written to detect overwrites */
void *allocate(int size)

This function should take a size_t value as argument. Many systems
have smaller int than size_t, and this unnecessarily restricts
what can be allocated. For example most 64-bit systems have 32-bit
int and 64-bit size_t.
.... snip code ...
>
On an implementation with int less than 32 bits, you just mangled
your signature. According to the C99 standard, when converting
integer values to a type in which the value is not representable:
"either the result is implementation-defined or an
implementation-defined signal is raised".
Rather than such faulty code, Jacob might be well advised to look
at my nmalloc module and its associated malldbg module. This is
available under the terms of DJGPP copying, i.e. essentially
unrestricted, although I retain copyright. Malldbg implements
various things that are often available under *IX systems, and is
well decoupled from the malloc module proper. It even includes a
..txh documentation module, ready for inclusion in other
documentation and capable of generating virtually any form of
documentation.

In his environment the only question is whether sbrk or the
equivalent is available as a system call. The calls to the
debugging macros can all be stripped to utilize a non-gcc compiler.

It would be trivial to add a function to malldbg.c/h which returns
the actual allocation size (which may have been rounded up from the
original malloc call). This should return zero for any pointer
that is not malloced, and the detection is possible, although not
absolutely positive.

size_t mallsize(void *p); /* highly non-standard */

<http://cbfalconer.home.att.net/download>

--
Merry Christmas, Happy Hanukah, Happy New Year
Joyeux Noel, Bonne Annee.
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>

Dec 29 '06 #22

P: n/a
Simon Biber a écrit :
jacob navia wrote:
>Replace all your malloc calls with this two functions.
They will allow you to know immediately the size of an
allocated object, besides giving you more security in handling
pointers, since they can give you a hint if the passed
pointer really points to an allocated buffer.
-------------------------------------------------------------cut here
/* this will be written at the end of the allocated block.
If this is overwritten it means something has written
beyond the block */
#define MAGIC 0xFFFF
/* This signature will be written at the start of the
allocated block to avoid freeing memory that wasn't
allocated at all */
#define SIGNATURE 12345678L
/* This variable counts the size of the memory allocated
so far. This is useful for detecting memory leaks */
static long AllocatedMemory;
/* This allocates a block, writing the signature, then
the size of the block. The useful data starts after
those two ints. At the end of the block, the "MAGIC"
number is written to detect overwrites */
void *allocate(int size)


This function should take a size_t value as argument. Many systems have
smaller int than size_t, and this unnecessarily restricts what can be
allocated. For example most 64-bit systems have 32-bit int and 64-bit
size_t.
The problem with size_t is that if you give it -4 it will try to
allocate 4GB...

Note the test for size <= 0 further below
>{
register char *r;
register int *ip = NULL;

if (size <= 0)
return NULL;
size += 3 * sizeof(int);
r = malloc((size_t)size);
if (r == NULL)
return NULL;
memset(r, 0, (size_t) size);
AllocatedMemory += size;
ip = (int *) r;
*ip++ = SIGNATURE;


On an implementation with int less than 32 bits, you just mangled your
signature. According to the C99 standard, when converting integer values
to a type in which the value is not representable: "either the result is
implementation-defined or an implementation-defined signal is raised".
Yes, you may use another signature in another environment. Anyway
since it is an arbitrary number, the result is the same, since we are
not interested in the value but in, the fact that we find it again

> *ip++ = size;


If you took my advice to make size a size_t object, then the same
problem applies here: you're forcing it into an int.
Yes, As I explained above.
> memset(ip, 0, size - 3*sizeof(int));
ip = (int *) (&r[size - sizeof(int)]);
*ip = MAGIC;


If size was not a multiple of sizeof(int) then this will be an unaligned
access. Such accesses will trap on many implementations. For example, on
the Sun SPARC architecture.

In addition, if int is 16 bits then 0xFFFF is outside the range of
signed int, and the implementation-defined result or signal referred to
above may occur.
> return (r + 2 * sizeof(int));


It's possible that 2*sizeof(int) is not sufficient alignment for some
larger types. For example, if sizeof(int) is 2 but sizeof(long long) is
8 and long long requires 8-byte alignment then one will not be able to
store long longs into this block. Also, if sizeof(int) is 4 but
sizeof(long double) is 16 and requires 16-byte alignment then one will
not be able to store long doubles into this block.
Can you tell me which implementation has int with 2 bytes and
long long with 8? I would like to know...
>}

[...]
>/* This will return the size of a block or -1 if it is not
a valid block
*/
int GetSize(void *block)
{
int *ip = block;

ip -= 2;
if (*ip != SIGNATURE)
return -1;
ip++;
return *ip;
}


If it is not a valid block as allocated by the allocate function above,
then trying to read two ints before the pointed-to location will
probably go outside of the object pointed to. This is of course
undefined behaviour, and may result in a segmentation fault.
Yes, a good thing. It will crash if you do pas it a nonsense
pointer. In most cases it will return -1.

Perfectly OK as behavior.
Dec 29 '06 #23

P: n/a
CBFalconer a écrit :
>
Rather than such faulty code, Jacob might be well advised to look
at my nmalloc module and its associated malldbg module.
OK Chuck, I will look into it but my code is not "faulty".
It *could* crash in some machines because the size is
not aligned, that's all.
Dec 29 '06 #24

P: n/a
On Fri, 29 Dec 2006 18:14:21 +0100, in comp.lang.c , jacob navia
<ja***@jacob.remcomp.frwrote:
>CBFalconer a écrit :
>>
Rather than such faulty code, Jacob might be well advised to look
at my nmalloc module and its associated malldbg module.

OK Chuck, I will look into it but my code is not "faulty".
It *could* crash in some machines because the size is
not aligned, that's all.
I think Simon pointed out a few other issues, for what its worth.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Dec 29 '06 #25

P: n/a
On Fri, 29 Dec 2006 18:12:57 +0100, in comp.lang.c , jacob navia
<ja***@jacob.remcomp.frwrote:
>Simon Biber a écrit :
>>
This function should take a size_t value as argument. Many systems have
smaller int than size_t, and this unnecessarily restricts what can be
allocated. For example most 64-bit systems have 32-bit int and 64-bit
size_t.
The problem with size_t is that if you give it -4 it will try to
allocate 4GB...
Simon's point was that many systems can allocate more memory than an
int's worth. The proposed function would be defective on such systems.
The negative is easily catered for (as indeed you did), plus quite
frankly if the documentation says "must be a positive value" then
anyone passing a -ve number deserves what they get - tell them to
RTFM.
>Note the test for size <= 0 further below
Yes, though returning NULL is possibly not the ideal fix. It would get
implementation dependent, but I'd consider some means to notify the
user.
>>According to the C99 standard, when converting integer values
to a type in which the value is not representable: "either the result is
implementation-defined or an implementation-defined signal is raised".

Yes, you may use another signature in another environment. Anyway
since it is an arbitrary number, the result is the same, since we are
not interested in the value but in, the fact that we find it again
Now that we know about this issue, this code is now *by design*
nonportable. That seems a peculiar decision, especially since the fix
is trivial.
>If you took my advice to make size a size_t object, then the same
problem applies here: you're forcing it into an int.

Yes, As I explained above.
Again, code is now "broken" by design.
>
Yes, a good thing. It will crash if you do pas it a nonsense
pointer. In most cases it will return -1.

Perfectly OK as behavior.
Et tu, brute?

Remind me who it was in a different thread that was advocating maximum
safety and automation? Could it be the same person now saying its ok
to crash if getting unexpected inputs?

But as long as its documented, I agree its ok, though not ideal.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Dec 29 '06 #26

P: n/a
On Fri, 29 Dec 2006 11:12:57 -0600, jacob navia wrote
(in article <45***********************@news.orange.fr>):
Simon Biber a écrit :
>jacob navia wrote:
>>Replace all your malloc calls with this two functions.
They will allow you to know immediately the size of an
allocated object, besides giving you more security in handling
pointers, since they can give you a hint if the passed
pointer really points to an allocated buffer.
-------------------------------------------------------------cut here
/* this will be written at the end of the allocated block.
If this is overwritten it means something has written
beyond the block */
#define MAGIC 0xFFFF
/* This signature will be written at the start of the
allocated block to avoid freeing memory that wasn't
allocated at all */
#define SIGNATURE 12345678L
/* This variable counts the size of the memory allocated
so far. This is useful for detecting memory leaks */
static long AllocatedMemory;
/* This allocates a block, writing the signature, then
the size of the block. The useful data starts after
those two ints. At the end of the block, the "MAGIC"
number is written to detect overwrites */
void *allocate(int size)


This function should take a size_t value as argument. Many systems have
smaller int than size_t, and this unnecessarily restricts what can be
allocated. For example most 64-bit systems have 32-bit int and 64-bit
size_t.
The problem with size_t is that if you give it -4 it will try to
allocate 4GB...
You eschew proper data types for faulty ones for a given problem space
because someone might feed it garbage input, rather than putting in
place a method to ensure reasonable input.

Nevermind that people could easily want to request more memory than
possible under a 32-bit int on 64-bit systems. I guess they don't
matter, because you don't think it's likely.

One look at the prototype for malloc() should be enough to tell us who
is correct, and who is wrong. Or, are you suggesting that the
parameter to malloc() should be of type int instead and that the
standard is flawed in that regard?

--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw

Dec 29 '06 #27

P: n/a
Mark McIntyre a écrit :
Simon's point was that many systems can allocate more memory than an
int's worth. The proposed function would be defective on such systems.
Maybe. I really do not care. I proposed this
code to be helpful to somebody that asked a question.

Now you want me to develop a general allocator
for all machines in existence?

In any case you can only talk nonsense without ever
proposing some code to actually solve a problem.
>>Yes, a good thing. It will crash if you do pas it a nonsense
pointer. In most cases it will return -1.

Perfectly OK as behavior.
There is NO way in C to know if a pointer is valid
or not. You didn't know that?
>
Et tu, brute?

Remind me who it was in a different thread that was advocating maximum
safety and automation? Could it be the same person now saying its ok
to crash if getting unexpected inputs?
There is NO WAY I repeat, to find out if a pointer is valid
or not, at least under standard C. Under windows you can
do it but I am sure you would have cried like mad because
I use the windows API.

There is NO WAY that I can say something here that you have to
put your nose and triy to find something wrong with it.

Please stop this. I do not care about your opinion
Dec 29 '06 #28

P: n/a
jacob navia said:
CBFalconer a écrit :
>>
Rather than such faulty code, Jacob might be well advised to look
at my nmalloc module and its associated malldbg module.

OK Chuck, I will look into it but my code is not "faulty".
It *could* crash in some machines because the size is
not aligned, that's all.
....and you didn't document the fact when you presented the code. How is that
"not faulty"?

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 29 '06 #29

P: n/a
jacob navia said:

<snip>
There is NO way in C to know if a pointer is valid
or not. You didn't know that?
But there is. Didn't you know that? I'll tell you about it.

1) whenever you define a pointer, either point it to an object (or function,
if it's a function pointer) or set it to NULL. Make sure that, from now on,
you only ever give it a determinate value.

2) When a pointer value becomes indeterminate (e.g. free(ptr)), set the
pointer value to NULL immediately.

3) Before using a pointer, check to see whether it's NULL. If not, you know
it's valid, provided you followed the above rules.

<snip>
There is NO WAY that I can say something here that you have to
put your nose and triy to find something wrong with it.
We try to find stuff wrong with what Chris Torek writes, too. And Keith
Thompson. And Richard Bos. And everyone, basically. The differences between
them and you are as follows:

1) it's rather harder to find errors in their articles (but we still try);
2) when we do so, they're glad of the correction (or, if they disagree with
the error report, they are at least glad of the opportunity to clarify the
matter);
3) they care about the opinions of other language experts with regard to the
C language - they might not agree, but they're ready to listen.
Please stop this. I do not care about your opinion
If you don't want people to write replies to your Usenet articles, don't
write Usenet articles. If you are not interested in other people's
opinions, why bother with Usenet at all?

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 29 '06 #30

P: n/a
On Fri, 29 Dec 2006 20:38:17 +0100, in comp.lang.c , jacob navia
<ja***@jacob.remcomp.frwrote:
>Mark McIntyre a écrit :
>Simon's point was that many systems can allocate more memory than an
int's worth. The proposed function would be defective on such systems.

Maybe. I really do not care.
Yes, thats the problem. You don't care to listen to the opinions or
advice of others.
>I proposed this
code to be helpful to somebody that asked a question.
Thats absolutely fine, but you should know CLC well enough to expect
others to comment on and correct any errors in posts. Such corrections
are posted in the same spirit as your post, ie to be helpful, and it
is extremely important not to take offense at or respond defensively
to such additions.
>>>Yes, a good thing. It will crash if you do pas it a nonsense
pointer. In most cases it will return -1.

Perfectly OK as behavior.

There is NO way in C to know if a pointer is valid
or not. You didn't know that?
You could always initialise it to point to a valid object.
>There is NO WAY I repeat, to find out if a pointer is valid
Quite. Its impossible to tell if some random value stored in a pointer
type is usable. Many people advocate only using valid pointers to
avoid this issue...
>There is NO WAY that I can say something here that you have to
put your nose and triy to find something wrong with it.
For what its worth, most of my post was positive, as was another post
I made in response to one of yours earlier. I have no grudge against
you, no beef with you or your application, no axe to grind, no
favorites to play. I do however have a beef against people posting
incorrect, inapplicable or nonsensical advice.
>Please stop this.
I will continue to comment on all and any post that I want to. As and
when I notice something I feel I can contribute to, I will do so. If
someone corrects me, I'll do my best to accept it with grace. If I
notice something thats wrong I'll do my best to correct it politely. I
don't promise to remain civil if I get gratuitously flamed in
response.
>I do not care about your opinion
Then stop reading my posts. Killfile me. Its that simple.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Dec 29 '06 #31

P: n/a
jacob navia wrote:
CBFalconer a écrit :
>Rather than such faulty code, Jacob might be well advised to look
at my nmalloc module and its associated malldbg module.

OK Chuck, I will look into it but my code is not "faulty". It
*could* crash in some machines because the size is not aligned,
that's all.
Code that crashes is not faulty? This is a new one.

--
Merry Christmas, Happy Hanukah, Happy New Year
Joyeux Noel, Bonne Annee.
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Dec 30 '06 #32

P: n/a
jacob navia wrote:
Simon Biber a écrit :
>jacob navia wrote:
.... snip ...
>>>
void *allocate(int size)
.... snip ...
>>
This function should take a size_t value as argument. Many
systems have smaller int than size_t, and this unnecessarily
restricts what can be allocated. For example most 64-bit systems
have 32-bit int and 64-bit size_t.
The problem with size_t is that if you give it -4 it will try to
allocate 4GB...
and then get rejected by malloc. At least nmalloc. So what?

--
Merry Christmas, Happy Hanukah, Happy New Year
Joyeux Noel, Bonne Annee.
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Dec 30 '06 #33

P: n/a
jacob navia wrote:
Mark McIntyre a écrit :
>Simon's point was that many systems can allocate more memory than
an int's worth. The proposed function would be defective on such
systems.

Maybe. I really do not care. I proposed this
code to be helpful to somebody that asked a question.

Now you want me to develop a general allocator
for all machines in existence?
That is inherently impossible. That's why malloc etc. is a system
provided mechanism. If you know what ISO C provides, you can
document the non-standard assumptions needed for a particular code
module to function. Having done so you have a good idea whether or
not a port to another system is easy, feasible, hard, or
impossible.

--
Merry Christmas, Happy Hanukah, Happy New Year
Joyeux Noel, Bonne Annee.
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Dec 30 '06 #34

P: n/a
jacob navia wrote:
Mark McIntyre a écrit :
>Simon's point was that many systems can allocate more memory than
an int's worth. The proposed function would be defective on such
systems.
.... snip ...
>
There is NO WAY that I can say something here that you have to
put your nose and triy to find something wrong with it.

Please stop this. I do not care about your opinion
But WE care that other readers do not receive bad advice. Thus
anything erroneous requires correction from somebody. The
criterion for erroneous involves the C standard. With luck all the
errors will be picked up.

Newbies in general should not take newsgroup advice too seriously
without waiting at least a few days for criticisms to appear.
Regulars would do well to learn something from their exposed
mistakes.

--
Merry Christmas, Happy Hanukah, Happy New Year
Joyeux Noel, Bonne Annee.
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Dec 30 '06 #35

P: n/a
On Fri, 29 Dec 2006 16:08:57 -0600, CBFalconer wrote
(in article <45***************@yahoo.com>):
jacob navia wrote:
>Simon Biber a écrit :
>>jacob navia wrote:
... snip ...
>>>>
void *allocate(int size)
... snip ...
>>>
This function should take a size_t value as argument. Many
systems have smaller int than size_t, and this unnecessarily
restricts what can be allocated. For example most 64-bit systems
have 32-bit int and 64-bit size_t.
The problem with size_t is that if you give it -4 it will try to
allocate 4GB...

and then get rejected by malloc. At least nmalloc. So what?
Why would it automatically be rejected? On some platforms, a request
for 4GB of RAM could be reasonable. I've worked on systems with 8
physical CPUs and 64GB of RAM. That's not a totally unreasonable
number.
--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw

Dec 30 '06 #36

P: n/a
Randy Howard wrote:
On Fri, 29 Dec 2006 16:08:57 -0600, CBFalconer wrote
(in article <45***************@yahoo.com>):
jacob navia wrote:
Simon Biber a écrit :
jacob navia wrote:
... snip ...
>>>
void *allocate(int size)
... snip ...
>>
This function should take a size_t value as argument. Many
systems have smaller int than size_t, and this unnecessarily
restricts what can be allocated. For example most 64-bit systems
have 32-bit int and 64-bit size_t.

The problem with size_t is that if you give it -4 it will try to
allocate 4GB...
and then get rejected by malloc. At least nmalloc. So what?

Why would it automatically be rejected?
Because nmalloc contains a check specifically for this.

Dec 30 '06 #37

P: n/a
Randy Howard wrote:
On Fri, 29 Dec 2006 16:08:57 -0600, CBFalconer wrote
>jacob navia wrote:
>>Simon Biber a écrit :
jacob navia wrote:
... snip ...
>>>>>
void *allocate(int size)
... snip ...
>>>>
This function should take a size_t value as argument. Many
systems have smaller int than size_t, and this unnecessarily
restricts what can be allocated. For example most 64-bit systems
have 32-bit int and 64-bit size_t.

The problem with size_t is that if you give it -4 it will try to
allocate 4GB...

and then get rejected by malloc. At least nmalloc. So what?

Why would it automatically be rejected? On some platforms, a request
for 4GB of RAM could be reasonable. I've worked on systems with 8
physical CPUs and 64GB of RAM. That's not a totally unreasonable
number.
Then it doesn't get rejected. But nothing says it has to be
accepted. In the case of nmalloc restriction to ((2 exp 31) -
65536) prevents ever confusing sbrk with a request to decrease
allocation. Among the reasons malloc packages are non-portable.

--
Merry Christmas, Happy Hanukah, Happy New Year
Joyeux Noel, Bonne Annee.
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Dec 30 '06 #38

P: n/a
On Thu, 28 Dec 2006 12:08:23 -0500, CBFalconer <cb********@yahoo.com>
wrote:
>Harald van D?k wrote:
>>
... snip ...
>>
Checking for a C++ compiler using the __cplusplus macro may not be
strictly conforming in C90, but I believe it is currently 100%
portable. It is possible someone will write a malicious C compiler in
the future, but I would be extremely surprised if such a compiler
exists already, because if it did, I would expect it would be common
knowledge on this newsgroup already. Similarly, __STDC_VERSION__ cannot
be used if you wish to keep your code strictly conforming C90, but I
can't remember seeing any objections to it for that reason in this
newsgroup.

#if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)

The value of an undefined id is 0.
That's a bug in C.

If a preprocessor comparison operator is used with an undefined "id",
the preprocessor should consider that an error.

I ran across a similar problem recently. The solution was to insure
the "id" was defined, before using it. For example:

#ifndef __STDC_VERSION__
#error "__STDC_VERSION__ not defined ... try again"
#endif
#if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)

It's sad one has to do these types of things to make things work with
Standard C. Especially when these types of things may cost you one or
more sleepless nights.

Happy New Year
--
jay
Dec 30 '06 #39

P: n/a
On Sat, 30 Dec 2006 00:42:56 -0800, in comp.lang.c , jaysome
<ja*****@hotmail.comwrote:
>On Thu, 28 Dec 2006 12:08:23 -0500, CBFalconer <cb********@yahoo.com>
wrote:
>>
#if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)

The value of an undefined id is 0.

That's a bug in C.
no, its a feature :-)

Personally I think its correct behaviour. Your example below of
__STDC_VERSION__ is using the macro wrongly, IMHO. If the value isn't
defined then it actually tells you something about the environment.
>It's sad one has to do these types of things to make things work with
Standard C. Especially when these types of things may cost you one or
more sleepless nights.
It makes one use macros more carefully, sure. Thats probably a good
thing too.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Dec 30 '06 #40

P: n/a
Mark McIntyre <ma**********@spamcop.netwrites:
On Sat, 30 Dec 2006 00:42:56 -0800, in comp.lang.c , jaysome
<ja*****@hotmail.comwrote:
>>On Thu, 28 Dec 2006 12:08:23 -0500, CBFalconer <cb********@yahoo.com>
wrote:
>>>
#if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)

The value of an undefined id is 0.

That's a bug in C.

no, its a feature :-)
Yes, but it's a feature with some pitfalls. For example, if I
accidentally type:

#if __STDC_VERSION_ >= 199901L
// code that depends on C99
#else
/* code that depends only on C90 */
#endif

then the compiler won't complain about the typo. The result in this
case is that it will always use the C90-specific code (which will
probably work correctly with a C99 compiler), and the C99-specific
code won't be tested.

I think if I were designing the language from scratch, I'd make a
reference to an undefined symbol an error. Of course, making such a
change now would break existing code.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 30 '06 #41

P: n/a
On Fri, 29 Dec 2006 17:08:57 -0500,
CBFalconer <cb********@yahoo.comwrote:
>jacob navia wrote:
>>Simon Biber a écrit :
>>jacob navia wrote:
... snip ...
>>>>
void *allocate(int size)
... snip ...
>>>
This function should take a size_t value as argument. Many
systems have smaller int than size_t, and this unnecessarily
restricts what can be allocated. For example most 64-bit systems
have 32-bit int and 64-bit size_t.

The problem with size_t is that if you give it -4 it will try to
allocate 4GB...

and then get rejected by malloc. At least nmalloc. So what?
Unless there *is* enough memory to satisfy the allocation request,
right? :)

jacob is also trying to blame programmer error (using a negative, signed
value as a 'size_t') to the size_t type itself. What he fails to supply
is a `type which is better than size_t for representing object sizes'.

He seems to imply that 'int' is better, but we all know it isn't.

Jan 1 '07 #42

P: n/a
"Giorgos Keramidas" <ke******@ceid.upatras.grwrote in message
news:87************@kobe.laptop...
On Fri, 29 Dec 2006 17:08:57 -0500,
CBFalconer <cb********@yahoo.comwrote:
>>jacob navia wrote:
>>The problem with size_t is that if you give it -4 it will try to
allocate 4GB...

and then get rejected by malloc. At least nmalloc. So what?

Unless there *is* enough memory to satisfy the allocation request,
right? :)
In theory. I'm curious if there is any existing 32- or 64-bit
implementation that can _ever_ successfully allocate (size_t)(-4) bytes.
None of the x86 or x64 OSes I know can, due to various "holes" in the
address space -- even RedHat's oddball Linux/x86 kernel that allows ~4GB
user space.

Clearly, it can succeed on systems that have a 16-bit size_t, such as
MS-DOS (and clones). Of course, using an int on such a system just adds
insult to injury, since it restricts you to allocating 32,767 bytes at a
time.
jacob is also trying to blame programmer error (using a negative,
signed
value as a 'size_t') to the size_t type itself. What he fails to
supply
is a `type which is better than size_t for representing object sizes'.

He seems to imply that 'int' is better, but we all know it isn't.
And, to be clear, the above 32,767-byte restriction holds in theory for
all systems; int isn't required to hold anything larger, and portable
code can't assume it does. int is clearly a bad choice for a memory
size argument in portable code.

If Jacob wants a signed argument to malloc(), he should at least be
proposing ssize_t (of course, assuming ISO standardized the POSIX
definition). However, the whole concept of allowing negative memory
sizes is just absurd to begin with. It catches one very obscure bug
which is likely to be caught anyways because malloc(-4) is unlikely to
ever work, is only likely to be made in extremely rare circumstances,
and is easily discovered with a debugger -- and in return it cuts the
amount of memory one can allocate in half, which is a pretty severe
limitation for some real-world apps that need >2GB of memory on 32-bit
systems.

S

--
Stephen Sprunk "God does not play dice." --Albert Einstein
CCIE #3723 "God is an inveterate gambler, and He throws the
K5SSS dice at every possible opportunity." --Stephen Hawking
--
Posted via a free Usenet account from http://www.teranews.com

Jan 2 '07 #43

P: n/a
On Mon, 1 Jan 2007 22:30:05 -0600, "Stephen Sprunk" <st*****@sprunk.orgwrote:
>"Giorgos Keramidas" <ke******@ceid.upatras.grwrote in message
news:87************@kobe.laptop...
>On Fri, 29 Dec 2006 17:08:57 -0500,
CBFalconer <cb********@yahoo.comwrote:
>>>jacob navia wrote:
The problem with size_t is that if you give it -4 it will try to
allocate 4GB...

and then get rejected by malloc. At least nmalloc. So what?

Unless there *is* enough memory to satisfy the allocation request,
right? :)

In theory. I'm curious if there is any existing 32- or 64-bit
implementation that can _ever_ successfully allocate (size_t)(-4)
bytes. None of the x86 or x64 OSes I know can, due to various "holes"
in the address space -- even RedHat's oddball Linux/x86 kernel that
allows ~4GB user space.
You're right of course. I should have stated more clearly that I had
arithmetically smaller values than -4 in mind.
Clearly, it can succeed on systems that have a 16-bit size_t, such as
MS-DOS (and clones). Of course, using an int on such a system just
adds insult to injury, since it restricts you to allocating 32,767
bytes at a time.
Exactly, thanks for putting in better words what I wrote :)

Jan 3 '07 #44

This discussion thread is closed

Replies have been disabled for this discussion.