Malloc and free questions - learner questions

R

Richard Heathfield

Cong Wang said:
What's wrong with alloca() ?

It doesn't exist, at least not when you're wearing comp.lang.c filters on
your specs. (Non-standard functions are considered atopical in clc.)
 
R

Richard Heathfield

clayne said:
Good luck, you're going to get slammed for mentioning alloca() just as
I mentioned assert().

You weren't slammed for mentioning assert. You were criticised for using it
in a sub-optimal way.
 
B

Bill Pursell

Richard said:
Bill Pursell said:

a has type T *.
So &a has type T **.

You pick it up as a void *, right?

Okay, so where do you go from there? You can't deref it, because if you have
void *ptr, you can't do *ptr. And if you do this instead: void **ptr; you
lose the automatic conversion.

In short, I'd be fascinated to see the source to my_malloc. :)

Well, I'm sitting at a public windows box at the moment (the only
redeeming quality of Google Groups!!), so I don't even have access
to a compiler, but I believe it looks like this:
(I changed the declaration slightly to make the
do loop easier to code).

error_t my_malloc(void *a, ...)
{
va_list ap;
size_t s;
error_t status;

status = 0;
va_start (ap, a);
do {
s = va_arg(ap, size_t);

if ( ( *a = malloc(s)) == NULL)
status = -1;
a = va_arg(ap, void *);
} while ( a != NULL);
if ( status == -1) {
/* go through the argument list, freeing and setting to
NULL*/
}

va_end(ap);
return ret;
}
 
R

Richard Heathfield

Bill Pursell said:

error_t my_malloc(void *a, ...)
{
va_list ap;
size_t s;
error_t status;

status = 0;
va_start (ap, a);
do {
s = va_arg(ap, size_t);

if ( ( *a = malloc(s)) == NULL)

But a has type void *, so you can't deref it.
 
B

Bill Pursell

Bill said:
Well, I'm sitting at a public windows box at the moment (the only
redeeming quality of Google Groups!!), so I don't even have access
to a compiler, but I believe it looks like this:
(I changed the declaration slightly to make the
do loop easier to code).

error_t my_malloc(void *a, ...)
{
va_list ap;
size_t s;
error_t status;

status = 0;
va_start (ap, a);
do {
s = va_arg(ap, size_t);

if ( ( *a = malloc(s)) == NULL)
status = -1;
a = va_arg(ap, void *);
} while ( a != NULL);
if ( status == -1) {
/* go through the argument list, freeing and setting to
NULL*/
}

va_end(ap);
return ret;
}

And now, I finally see your point....
I'm using something like this at work, so I will look at it tomorrow
and see what it is that I'm doing. I must be declaring the function
as taking void **. Feeling foolish at the moment.
 
B

Bill Pursell

Richard said:
Bill Pursell said:



But a has type void *, so you can't deref it.

Ah, hah! I recall: the declaration takes void **, and I call it with:
void *a;
struct foo *b;
my_malloc(&a, N, NULL);
b = a;

It's not the greatest, but it works out okay. Could probably also
make the call
my_malloc(&(void *)b, N, NULL), but I'm not a big fan of the cast.
 
R

Richard Heathfield

Bill Pursell said:

And now, I finally see your point....
I'm using something like this at work, so I will look at it tomorrow
and see what it is that I'm doing. I must be declaring the function
as taking void **. Feeling foolish at the moment.

The problem with void ** is that it does not have the same conversion
guarantees as void *.

You are not the first to try to solve this problem (function takes pointer
to generic pointer and updates its value). As far as I am aware, no
standard solution exists - but don't let that stop you trying. :)
 
P

pkirk25

char *temp_string = malloc(MAXLEN);

if (NULL == temp_string)
{
/* malloc failed */
}

Is this a suitable check?
 
C

Christopher Layne

pkirk25 said:
char *temp_string = malloc(MAXLEN);

if (NULL == temp_string)
{
/* malloc failed */
}

Is this a suitable check?

Better than nothing. Although the thread itself has already shown plenty of
debate on which is the "best" way.
 
R

Richard Heathfield

Bill Pursell said:
Ah, hah! I recall: the declaration takes void **, and I call it with:
void *a;
struct foo *b;
my_malloc(&a, N, NULL);
b = a;

Blech. One might not mind doing the void * tango for /one/ pointer, but the
whole point of my_malloc is to take a whole set of them. Isn't the solution
clumsier than the problem it's trying to fix?

It's not the greatest, but it works out okay. Could probably also
make the call
my_malloc(&(void *)b, N, NULL), but I'm not a big fan of the cast.

A cast yields an expression, not an object or function. Your code violates a
constraint:

"The operand of the unary & operator shall be either a function
designator or an lvalue that designates an object that is not a
bit-field and is not declared with the register storage-class
specifier."

so a diagnostic is required.
 
R

Richard Heathfield

pkirk25 said:
char *temp_string = malloc(MAXLEN);

if (NULL == temp_string)
{
/* malloc failed */
}

Is this a suitable check?

Yes, the check is fine. The trick is what you do next. How does your program
react to a failure to acquire that necessary resource? Do you just throw in
the towel, or do you try to recover fully in some way, or do you attempt to
do some kind of damage limitation (e.g. save data) and /then/ head for the
door?
 
M

Malcolm

pkirk25 said:
If I start a function with this:
char *temp_string = malloc(MAXLEN);
char *item_id_string = malloc(MAXLEN);
char *item_description_string = malloc(MAXLEN);

Can I assume that malloc does exactly as its told or so I need to
check?

When the function finishes, it the memory freed up or do I need to
explicitly call free(temp_string) at end and free(item_id_string)
free(item_description_string ) after I am finished with them?

I can tell these are newbie type questions but K&R is very terse on
this subject.
Nowadays malloc() never fails, at least for small allocations.
The computer is far more likely to break than to fail to deliver a kilobyte
of memory.

However the standard says it can fail, so to be strictly correct you need to
check it.
 
G

Giorgio Silvestri

Andrea Laforgia said:
[...]

You must always check whether malloc() succeeded or not by examining
its return value: if 0 (NULL) it failed. If malloc() succeeds, then
the size of the memory allocated is exactly what you specified.

[...]

Not necessarily, memory allocated can be more than requested.
 
C

Christopher Layne

Giorgio said:
You must always check whether malloc() succeeded or not by examining
its return value: if 0 (NULL) it failed. If malloc() succeeds, then
the size of the memory allocated is exactly what you specified.

[...]

Not necessarily, memory allocated can be more than requested.

As far as the caller is concerned, that's none of their concern, however. Not
saying it isn't something to consider, but it's not to be taken advantage of.
 
P

pkirk25

Yes, the check is fine. The trick is what you do next. How does your program
react to a failure to acquire that necessary resource? Do you just throw in
the towel, or do you try to recover fully in some way, or do you attempt to
do some kind of damage limitation (e.g. save data) and /then/ head for the
door?

If it fails, optimization goes out the window and I pass by value.

My impression is that when it fails, you can face hours of misery.
 
R

Richard Heathfield

pkirk25 said:
If it fails, optimization goes out the window and I pass by value.

My impression is that when it fails, you can face hours of misery.

No, you just need to realise that an important part of programming consists
of answering the following questions:

1) what external resources do I need, to get the job done?
2) can I get them?
3) what should I do if I can't? Are there alternatives? Or should I just
give up? How do I fail gracefully?

So - let's say you're trying to open a file, supposedly given by the user on
argv[1]. Do you fopen(argv[1], "r"); ? Nope, not until you've checked that
argc > 1. And what if it isn't? No point in going on without data. Should
you look for data on stdin instead? Or should you ask the user to use stdin
to provide a filename?

Okay, so you need some memory to do - well, whatever. Let's just imagine a
situation where you can't have it, for whatever reason. So - would it be
okay to have two blocks, each half the size? Would that work for you? If
so, you have a possible failure recovery strategy (because an allocator may
not be able to give you one contiguous lump of N bytes, but may have
several lumps that are >= N/2 bytes in size).

That's one possible recovery strategy. There are others. Which ones you go
for depend on what you're doing, what your situation is.
 
M

Malcolm

Richard Heathfield said:
Malcolm said:


ROTFL!

See Eric Sosman's article elsethread.
Now I've outsourced all my processing to China, I've got over a billion
people slaving away for me.
So I can ask them to give an ascii character, which they can't read being
Chinese, to a thousand people, a thousand thousand times. We have the
inevitable occasional hitch, and downtime is more than one in a million
runs.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top