473,372 Members | 930 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,372 software developers and data experts.

alligned memory allocation

Hi,
I ve got the following piece of code which does the role of allocating
aligned memory (not sure what aligned memory allocation is either).

void *
_align_calloc(size_t bytes, unsigned long alignment)
{
unsigned long ptr, buf;

ASSERT( alignment > 0 );

ptr = (unsigned long) calloc(bytes + alignment + sizeof(void *));
if (!ptr)
return NULL;

buf = (ptr + alignment + sizeof(void *)) & ~(unsigned long)(alignment -
1);
*(unsigned long *)(buf - sizeof(void *)) = ptr;

#ifdef DEBUG
/* mark the non-aligned area */
while ( ptr < buf - sizeof(void *) ) {
*(unsigned long *)ptr = 0xcdcdcdcd;
ptr += sizeof(unsigned long);
}
#endif

return (void *)buf;
}

Can somebody please explain what this code is doing? I m a little confused
with the memory being allocated to a non pointer data namely unsigned long
ptr ?
kutty
Nov 14 '05 #1
13 8105
In article <c2***********@bigboote.WPI.EDU>,
"Kutty Banerjee" <ku****@wpi.edu> wrote:
Hi,
I ve got the following piece of code which does the role of allocating
aligned memory (not sure what aligned memory allocation is either).

void *
_align_calloc(size_t bytes, unsigned long alignment)
{
unsigned long ptr, buf;

ASSERT( alignment > 0 );

ptr = (unsigned long) calloc(bytes + alignment + sizeof(void *));
if (!ptr)
return NULL;

buf = (ptr + alignment + sizeof(void *)) & ~(unsigned long)(alignment -
1);
*(unsigned long *)(buf - sizeof(void *)) = ptr;

#ifdef DEBUG
/* mark the non-aligned area */
while ( ptr < buf - sizeof(void *) ) {
*(unsigned long *)ptr = 0xcdcdcdcd;
ptr += sizeof(unsigned long);
}
#endif

return (void *)buf;
}

Can somebody please explain what this code is doing? I m a little confused
with the memory being allocated to a non pointer data namely unsigned long
ptr ?


It is a case of a clueless programmer trying to return a pointer that is
aligned in a certain way. I'll give you an overview what he is trying to
do and where he gets it wrong:

malloc and calloc return pointers that are properly aligned for _any_ C
type. Now there might be reasons why you would want a pointer that is
aligned to multiples of 128 bytes, for example, and malloc won't do
that.

So what he does is allocate a pointer that is bigger, lets say a pointer
"char* p", and in the case of 128 byte alignment you would add some
value from 0 to 127 to make it aligned on a multiple of 128 bytes. But
if you did just that and returned the result pointer, then you wouldn't
be able to free the memory later: To be able to call free, you must have
the original pointer. So you store the original pointer just in front of
the pointer that you return.

Now your original author does a few remarkably stupid things. He makes
assumptions that are completely unwarranted in portable C and actually
wrong on more and more computers that are in actual use. No wonder you
are confused :-(

First, he assumes that "alignment" is not only greater than zero, but
also a power of two, AND at least as large as the alignment requirement
of a void* value. Why doesn't he write this in the ASSERT? To test
whether x is a power of two: If you write x and x-1 in binary, then if x
is a power of two no bit will be set both in x and x-1. If x is nonzero
and not a power of two, then the highest bit of x is also set in x-1. So
you could write

ASSERT(align >= sizeof (void *) && (align & (align-1)) != 0);

Next, he assumes that you can cast a void* to unsigned long and perform
pointer arithmetic on the unsigned long. Bullshit. Take an Athlon 64 and
you may be surprised to see that void* = 64 bit, unsigned long = 32 bit,
and casting void* to unsigned long produces a whole lot of garbage. Take
16 bit DOS with "huge" memory model, and adding to an unsigned long to
do pointer arithmetic will produce garbage. Try it on a Cray and heaven
knows what you get. But in fact it is very easy to do what he wants in a
much more portable way:

char* p = calloc (bytes + alignment + sizeof (void *));
char* q = p + sizeof (void *) + alignment;
q -= ((unsigned long) q) % alignment;

// If you want your code unreadable like the original author,
// then change the last line to
// q -= ((unsigned long) q) & (alignment - 1);

Now it doesn't matter what the relative sizes of pointers and unsigned
long are.

The next mistake that he makes is that you can store an unsigned long if
you have space for a void*. Bad mistake. Just as you have systems where
sizeof (void *) > sizeof (unsigned long), you have systems where it is
the other way round. Buy a new Macintosh and you will get a machine that
uses 64 bit integers and 32 bit pointers. So he has this pointer "buf",
subtracts four byte = sizeof (void *), and stores an eight byte unsigned
long. Congratulations. The last four bytes of that unsigned long will be
overwritten by the caller as soon as they use the memory. Crash when you
try to free the memory later on.

Have fun with this guy's code. Expect the worst. People who think they
can program and can't are the worst kind.
Nov 14 '05 #2
Christian Bau wrote:
"Kutty Banerjee" <ku****@wpi.edu> wrote:
I ve got the following piece of code which does the role of
allocating aligned memory (not sure what aligned memory
allocation is either).

void *
_align_calloc(size_t bytes, unsigned long alignment)
{ .... snip code ...
Can somebody please explain what this code is doing? I m a
little confused with the memory being allocated to a non
pointer data namely unsigned long ptr ?
It is a case of a clueless programmer trying to return a pointer
that is aligned in a certain way. I'll give you an overview what
he is trying to do and where he gets it wrong:

.... snip ...
Have fun with this guy's code. Expect the worst. People who
think they can program and can't are the worst kind.


The code is obviously not portable, and is also obviously intended
for system use (the _align... name is not in the user name
space). This is a problem that is simply not soluble with
portable code, so the only requirement is that it work, somehow or
other, with the original implementation. Your caustic criticisms
are probably undeserved.

To the OP: The internal workings of a particular system are often
wierd and wonderful, and highly non-standard. You are not
expected to understand them on the basis of the language.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #3
In article <40***************@yahoo.com>,
CBFalconer <cb********@yahoo.com> wrote:
Christian Bau wrote:
Have fun with this guy's code. Expect the worst. People who
think they can program and can't are the worst kind.


The code is obviously not portable, and is also obviously intended
for system use (the _align... name is not in the user name
space). This is a problem that is simply not soluble with
portable code, so the only requirement is that it work, somehow or
other, with the original implementation. Your caustic criticisms
are probably undeserved.


The point is that this code is unportable without any good reason. And
assuming that unsigned long and void* have the same size, today, is just
utterly stupid. Not the "it works everywhere except on the DeathStation
9000" kind of stupid, but the "I bought this brand new computer and my
code crashes all over the place" kind of stupid.
Nov 14 '05 #4
Christian Bau wrote:
CBFalconer <cb********@yahoo.com> wrote:
Christian Bau wrote:

Have fun with this guy's code. Expect the worst. People who
think they can program and can't are the worst kind.


The code is obviously not portable, and is also obviously intended
for system use (the _align... name is not in the user name
space). This is a problem that is simply not soluble with
portable code, so the only requirement is that it work, somehow or
other, with the original implementation. Your caustic criticisms
are probably undeserved.


The point is that this code is unportable without any good reason.
And assuming that unsigned long and void* have the same size, today,
is just utterly stupid. Not the "it works everywhere except on the
DeathStation 9000" kind of stupid, but the "I bought this brand new
computer and my code crashes all over the place" kind of stupid.


You yourself pointed out a reason for it - to provide alignment to
larger values than does malloc. Unsigned long and void* may well
have the same size on that system, they do under DJGPP. I believe
gcc requires such system routines (although I don't approve).
This is probably not the forum to ask questions about it, although
I am hard pressed to think of a suitable newsgroup.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #5
CBFalconer <cb********@yahoo.com> wrote in message news:<40***************@yahoo.com>...
Christian Bau wrote:

<snip>

Have fun with this guy's code. Expect the worst. People who
think they can program and can't are the worst kind.


The code is obviously not portable, and is also obviously intended
for system use (the _align... name is not in the user name
space). This is a problem that is simply not soluble with
portable code, so the only requirement is that it work, somehow or
other, with the original implementation. Your caustic criticisms
are probably undeserved.


I strongly disagree. As Christian pointed out, the original code
chooses unportability even though choosing (more) portability is
essentially free.

In fact, to me it's more unmaintainable. If you're doing something
like this, I immediately wonder why the author did not simply call
memalign then memset. Or simply wrote a small function to round the
alignment to the nearest power of two and then do a memalign and
memset. Now I just spent time that I shouldn't have had to spend.

Bad code is bad code, whether it works on the original implementation
or not. The mark of a bad programmer is that they write portable code
when there's a reason to. The mark of a good programmer is that they
write portable code when there is no reason not to.

Mark F. Haigh
mf*****@sbcglobal.net
Nov 14 '05 #6
In article <40**************@yahoo.com>,
CBFalconer <cb********@yahoo.com> wrote:
Christian Bau wrote:
CBFalconer <cb********@yahoo.com> wrote:
Christian Bau wrote:
> Have fun with this guy's code. Expect the worst. People who
> think they can program and can't are the worst kind.

The code is obviously not portable, and is also obviously intended
for system use (the _align... name is not in the user name
space). This is a problem that is simply not soluble with
portable code, so the only requirement is that it work, somehow or
other, with the original implementation. Your caustic criticisms
are probably undeserved.


The point is that this code is unportable without any good reason.
And assuming that unsigned long and void* have the same size, today,
is just utterly stupid. Not the "it works everywhere except on the
DeathStation 9000" kind of stupid, but the "I bought this brand new
computer and my code crashes all over the place" kind of stupid.


You yourself pointed out a reason for it - to provide alignment to
larger values than does malloc. Unsigned long and void* may well
have the same size on that system, they do under DJGPP.

I believe
gcc requires such system routines (although I don't approve).
And I hope sincerely that they have been written better.
This is probably not the forum to ask questions about it, although
I am hard pressed to think of a suitable newsgroup.


char* p;
unsigned long x;

* (unsigned long *) (p - sizeof (void *)) = x;

is not non-portable, it is just plain stupid. The original poster was
confused _by the stupidity_ of the code. There were other errors in the
code that had nothing to do with portability, but just with stupidity.
Nov 14 '05 #7
Mark F. Haigh wrote:
CBFalconer <cb********@yahoo.com> wrote in message news:<40***************@yahoo.com>...
Christian Bau wrote:


<snip>
Have fun with this guy's code. Expect the worst. People who
think they can program and can't are the worst kind.


The code is obviously not portable, and is also obviously intended
for system use (the _align... name is not in the user name
space). This is a problem that is simply not soluble with
portable code, so the only requirement is that it work, somehow or
other, with the original implementation. Your caustic criticisms
are probably undeserved.

I strongly disagree. As Christian pointed out, the original code
chooses unportability even though choosing (more) portability is
essentially free.

In fact, to me it's more unmaintainable. If you're doing something
like this, I immediately wonder why the author did not simply call
memalign then memset. Or simply wrote a small function to round the
alignment to the nearest power of two and then do a memalign and
memset. Now I just spent time that I shouldn't have had to spend.

Bad code is bad code, whether it works on the original implementation
or not. The mark of a bad programmer is that they write portable code
when there's a reason to. The mark of a good programmer is that they
write portable code when there is no reason not to.


yeah, yeah, memalign not in C standard, or POSIX for that matter, yeah
yeah. My point remains essentially the same. If memalign, snprintf,
etc, are not implemented on your system, then implement 'em and use 'em.
Even at a glance, the entire _align_calloc thing the OP quoted should
jump out at you and say 'probably a bad idea'.

Some of these supposed systems programming guys come up with this kind
of thing and then throw casts around until the compiler shuts up. This
is neither weird nor wonderful, just annoying to those of us that have
to clean up afterwards.

Or maybe I'm just cynical, you decide.

Mark F. Haigh
mf*****@sbcglobal.net
Nov 14 '05 #8
In <40**************@yahoo.com> CBFalconer <cb********@yahoo.com> writes:
You yourself pointed out a reason for it - to provide alignment to
larger values than does malloc.


malloc provides maximally aligned blocks, *by definition*:

The pointer returned if the allocation succeeds
is suitably aligned so that it may be assigned to a pointer to
any type of object and then used to access such an object or an
^^^^^^^^^^^^^^^^^^
array of such objects in the space allocated (until the space
is explicitly deallocated).

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #9
Dan Pop wrote:
CBFalconer <cb********@yahoo.com> writes:
You yourself pointed out a reason for it - to provide alignment to
larger values than does malloc.


malloc provides maximally aligned blocks, *by definition*:

The pointer returned if the allocation succeeds
is suitably aligned so that it may be assigned to a pointer to
any type of object and then used to access such an object or an
^^^^^^^^^^^^^^^^^^
array of such objects in the space allocated (until the space
is explicitly deallocated).


For the C language. There are entities in the world other than C
language objects, and sometimes C code is used to organize and
manipulate them.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!

Nov 14 '05 #10
In <40***************@yahoo.com> CBFalconer <cb********@yahoo.com> writes:
Dan Pop wrote:
CBFalconer <cb********@yahoo.com> writes:
You yourself pointed out a reason for it - to provide alignment to
larger values than does malloc.


malloc provides maximally aligned blocks, *by definition*:

The pointer returned if the allocation succeeds
is suitably aligned so that it may be assigned to a pointer to
any type of object and then used to access such an object or an
^^^^^^^^^^^^^^^^^^
array of such objects in the space allocated (until the space
is explicitly deallocated).


For the C language. There are entities in the world other than C
language objects, and sometimes C code is used to organize and
manipulate them.


How is this possible, without treating them as C objects?

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #11
"Dan Pop" <Da*****@cern.ch> wrote in message
news:c2**********@sunnews.cern.ch...
In <40***************@yahoo.com> CBFalconer <cb********@yahoo.com> writes:
Dan Pop wrote:
CBFalconer <cb********@yahoo.com> writes:

You yourself pointed out a reason for it - to provide alignment to
larger values than does malloc.

malloc provides maximally aligned blocks, *by definition*:

The pointer returned if the allocation succeeds
is suitably aligned so that it may be assigned to a pointer to
any type of object and then used to access such an object or an
^^^^^^^^^^^^^^^^^^
array of such objects in the space allocated (until the space
is explicitly deallocated).


For the C language. There are entities in the world other than C
language objects, and sometimes C code is used to organize and
manipulate them.


How is this possible, without treating them as C objects?


Depends on the hardware on which the C program is
running, which means that the C code is not intended
to be portable to other platforms, yet still have
defined behavior and not use implementation-dependent
compiler features.

The IBM Mainframe has hardware structures of various
alignments, like 64-byte, 256-byte, 4096-byte,
1MB alignment, and larger. There is no C compiler
"object" that conforms to those alignments, yet
it's necessary to represent such requirements in
C code. That requires pointer<->integer conversions
and arithmetic that yield defined behavior. In such
cases, malloc() will not yield a properly aligned
"object". The usual approach is to "over allocate"
with malloc() and massage the pointer upward to an
appropriate alignment boundary, saving somewhere the
original pointer for a subsequent free().

A smart implementation of calloc() and malloc()
would examine the length to determine a plausible
maximum alignment and attempt to return a pointer
that conforms to the plausible max alignment, but
that is not a requirement. They only need to conform
to maximum alignment of a primitive C object (like
a "long long" or a "double", whatever is largest in
the implementation).
--
----------------------------
Jeffrey D. Smith
Farsight Systems Corporation
24 BURLINGTON DRIVE
LONGMONT, CO 80501-6906
http://www.farsight-systems.com
z/Debug debugs your Systems/C programs running on IBM z/OS!
Are ISV upgrade fees too high? Check our custom product development!
Nov 14 '05 #12
Dan Pop wrote:
CBFalconer <cb********@yahoo.com> writes:
Dan Pop wrote:
CBFalconer <cb********@yahoo.com> writes:

You yourself pointed out a reason for it - to provide alignment to
larger values than does malloc.

malloc provides maximally aligned blocks, *by definition*:

The pointer returned if the allocation succeeds
is suitably aligned so that it may be assigned to a pointer to
any type of object and then used to access such an object or an
^^^^^^^^^^^^^^^^^^
array of such objects in the space allocated (until the space
is explicitly deallocated).


For the C language. There are entities in the world other than C
language objects, and sometimes C code is used to organize and
manipulate them.


How is this possible, without treating them as C objects?


By taking advantage of system specific knowledge, and accepting
the non-portability of the result. Your system implementation of
malloc, free, and realloc is almost certainly a case in point. My
implementation of the same for DJGPP is certainly such. You can
find it on my site if curious.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #13
>>> CBFalconer <cb********@yahoo.com> writes:
You yourself pointed out a reason for it - to provide alignment to
larger values than does malloc.
Dan Pop wrote:
malloc provides maximally aligned blocks, *by definition*:
[snippage]
In <40***************@yahoo.com> CBFalconer <cb********@yahoo.com> writes:
For the C language. There are entities in the world other than C
language objects, and sometimes C code is used to organize and
manipulate them.

In article <news:c2**********@sunnews.cern.ch>
Dan Pop <Da*****@cern.ch> writes:How is this possible, without treating them as C objects?


By faking it, of course.

Typically one might build a struct or array that (by chance *and*
purpose both) corresponds to the hardware's requirements, then use
non-portable trickery to cause the existing mechanisms to produce
values that work with this.

The result is not guaranteed by the language, certainly, and often
even the compiler-vendor may not guarantee it (other than internally
if the vendor is also in the hardware or hardware-support business).
But if it works, and is more maintainable than (e.g.) writing the
entire thing in assembly, that may be enough to cause one to use it.

The fact that a "struct page_table" (for instance) can only be
allocated by the special "page table allocator", and:

struct page_table tmp;
... use &tmp ...

fails miserably, is relevant to someone who thinks the system is
written in ANSI/ISO C, but not so important one who knows it is
much more restricted than that. In other words, these non-C-objects
*sometimes* work like real C objects, and sometimes do not, and we
(I can speak for more than just myself here :-) ) pay this price
willingly for the value returned -- namely, some measure of
convenience. When it stops working well, we change the code
(and/or the compiler, in those cases where we control it).
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: chris | last post by:
Hi all, I need to know, what is the difference between dynamic memory allocation, and stack allocation ? 1. If I have a class named DestinationAddress, when should I use dynamic memory...
4
by: PaulR | last post by:
Hi, We have a Server running SLES 8 and 3GB memory, with 1 DB2 instance and 2 active Databases. General info... DB2level = "DB2 v8.1.0.72", "s040914", "MI00086", and FixPak "7" uname -a =...
62
by: ivan.leben | last post by:
How can I really delete a preloaded image from memory/disk cache? Let's say I preload an image by creating an Image object and setting its src attribute to desired URL: var img = new Image();...
66
by: Johan Tibell | last post by:
I've written a piece of code that uses sockets a lot (I know that sockets aren't portable C, this is not a question about sockets per se). Much of my code ended up looking like this: if...
24
by: Ken | last post by:
In C programming, I want to know in what situations we should use static memory allocation instead of dynamic memory allocation. My understanding is that static memory allocation like using array...
1
by: Peterwkc | last post by:
Hello all expert, i have two program which make me desperate bu after i have noticed the forum, my future is become brightness back. By the way, my problem is like this i the first program was...
34
by: jacob navia | last post by:
Suppose that you have a module that always allocates memory without ever releasing it because the guy that wrote it was lazy, as lazy as me. Now, you want to reuse it in a loop. What do you do?...
66
by: karthikbalaguru | last post by:
Hi, Will 'free' return the memory Immediately to the OS ? Thx in advans, Karthik Balaguru
4
by: Guilleuss | last post by:
Hi, In the alligned memory allocation post (a quite good article indeed). Christian Bau suggests the following: char* p = calloc (bytes + alignment + sizeof (void *)); char* q = p + sizeof...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.