malloc experiments

  • Thread starter Steve Zimmerman
  • Start date
R

Richard Heathfield

Randy said:
Perhaps. The response I received was basically (paraphrasing) "Thank you,
but I have asked on comp.lang.c about this in the past, and nobody could
point to a single system that would actually crash with void main()."

Firstly, that's not the point. The behaviour is undefined, and he shouldn't
be promulgating egregious undefined behaviour.

Secondly, I have searched the Google archives, and could find only one
article by Dan Gookin in comp.lang.c, which didn't mention main() at all.

Thirdly, several such hardware systems have been identified (did the author
think to check Google?), and it's trivial to construct a software system
that could crash on void main, even on a Microsoft platform:

@echo off
voidmainprg.exe
if errorlevel 2 goto spacecadet
if errorlevel 1 goto failed
echo It worked.
goto end
:spacecadet
echo Here we go...
rem insert your favourite Windows exploit here
spacecadet.exe
:failed
echo It failed.
:end

He did mention that the books were written before the standard

Huh? It was published in 1997, almost a decade /after/ the Standard.
 
R

Randy Howard

Firstly, that's not the point. The behaviour is undefined, and he shouldn't
be promulgating egregious undefined behaviour.

Just let me say that I wasn't defending it, I was just passing the info
along.
Huh? It was published in 1997, almost a decade /after/ the Standard.

I think he may have been referring to C99 (I know, I know...).
 
M

Martin Dickopp

Richard Heathfield said:
Randy said:
Perhaps. The response I received was basically (paraphrasing) "Thank you,
but I have asked on comp.lang.c about this in the past, and nobody could
point to a single system that would actually crash with void main()."
[...]

Thirdly, several such hardware systems have been identified (did the author
think to check Google?), and it's trivial to construct a software system
that could crash on void main, even on a Microsoft platform:

This has actually happend to me in a real situation. It was a rather long
and rather important script on a Unix system, and like all my scripts, it
was written in such a way that it immediately terminates if any program
reports an unsuccessful exit status (<OT> `set -e' in bash </OT>).

This script sometimes failed mysteriously, under hard-to-reproduce
circumstances. After much tinkering I found that one of the programs I
called used `void main' and returned a random exit status.

Martin
 
J

John Bode

Steve Zimmerman said:
The honest answer is, "No one taught me to cast malloc()'s return value.
I've never written any code using malloc." See

http://www.c-for-dummies.com/lessons/chapter.17

gak.

There's a reason that "for-dummies" type books and Web sites have a
bad reputation. Last time I checked there were on the order of 7.3354
x 10^13* books and Web sites purporting to teach C, and maybe 10 or
12** of them aren't crap. Although this isn't the worst I've ever
seen (Schildt's "C The Complete Reference", 1st ed. will forever hold
that particular honor), he definitely teaches some bad habits.

You can find a list of recommended, authoritative references for
introductory C programming at the following site:

http://www.accu.org/bookreviews/public/reviews/0sb/beginner_s_c.htm

* Okay, so maybe that's a *slight* exaggeration.
** That isn't.
 
R

Ravi Uday

[ snip ]
int main(void)
{
int wrong_return_type_malloc(size_t);
int *p;
...
p = (int *) wrong_return_type_malloc( foo );
...
}

Now, look at that cast. In the current program, it's *hiding*
the error from the compiler. (Remember that a cast always says
to the compiler, "Be quiet and let me do this my way, right or
wrong.") So this program will compile without diagnostics, and
run, and crash, because we're expecting 'malloc' to return an
'int' (by mechanism A) when really it's returning a 'void *' (by
mechanism B). Really, some machines will actually use different
registers for different types, and so on.
So our program crashes at runtime -- or, insidiously, doesn't
crash until the day of the big demo, when the boss is around.
So can i do something like this :
typedef struct mystr{
char *p;
int i[10];
}my_str;

int main (void)
{
void *data;
my_str *use;

data = malloc ( sizeof my_str);
use = ( my_str*)data ;
use->i[0] = 3333;

free ( use );
return 0;
}
So, everytime i need to use 'malloc', get its return value in a '
void* ' variable and then use this variable to cast according to my
requirement which can be of struct/int/char type. ? Is this correct.

Also what actually happens if variable 'p' is of my_str type.

p = malloc ( *p ); /* which seems to be the most suggested option ! */

- Ravi

[ snip ]
 
D

Default User

Dave said:
Fine, then, the value it would have returned had you used it.

Great, now you are arguing my side of the question.
(I should know better than to get myself into this sort of thing by now.)


How about, don't make dopey statements? Your premise was ludicrous.




Brian Rodenborn
 
J

Joe Wright

Ravi said:
[ snip ]
int main(void)
{
int wrong_return_type_malloc(size_t);
int *p;
...
p = (int *) wrong_return_type_malloc( foo );
...
}

Now, look at that cast. In the current program, it's *hiding*
the error from the compiler. (Remember that a cast always says
to the compiler, "Be quiet and let me do this my way, right or
wrong.") So this program will compile without diagnostics, and
run, and crash, because we're expecting 'malloc' to return an
'int' (by mechanism A) when really it's returning a 'void *' (by
mechanism B). Really, some machines will actually use different
registers for different types, and so on.
So our program crashes at runtime -- or, insidiously, doesn't
crash until the day of the big demo, when the boss is around.
So can i do something like this :
typedef struct mystr{
char *p;
int i[10];
}my_str;

int main (void)
{
void *data;
my_str *use;

data = malloc ( sizeof my_str);
use = ( my_str*)data ;
use->i[0] = 3333;

free ( use );
return 0;
}
So, everytime i need to use 'malloc', get its return value in a '
void* ' variable and then use this variable to cast according to my
requirement which can be of struct/int/char type. ? Is this correct.

Also what actually happens if variable 'p' is of my_str type.

p = malloc ( *p ); /* which seems to be the most suggested option ! */
Just a little finer maybe...

#include <stdlib.h>

typedef struct mystr {
struct mystr *p;
int i[10];
} my_str;

int main(void) {
my_str *use;
use = malloc( sizeof *use );
use->i[0] = 3333;
use->p = malloc( sizeof *use->p );
use->p->i[0] = 4444;

free( use->p );
free( use );
return 0;
}
 
P

Peter Nilsson

....
Just a little finer maybe...

#include <stdlib.h>

typedef struct mystr {
struct mystr *p;
int i[10];
} my_str;

int main(void) {
my_str *use;
use = malloc( sizeof *use );
use->i[0] = 3333;
use->p = malloc( sizeof *use->p );
use->p->i[0] = 4444;

free( use->p );
free( use );
return 0;
}

You should always check whether or not malloc returns a null pointer.
 
J

Joe Wright

Peter said:
...
Just a little finer maybe...

#include <stdlib.h>

typedef struct mystr {
struct mystr *p;
int i[10];
} my_str;

int main(void) {
my_str *use;
use = malloc( sizeof *use );
use->i[0] = 3333;
use->p = malloc( sizeof *use->p );
use->p->i[0] = 4444;

free( use->p );
free( use );
return 0;
}

You should always check whether or not malloc returns a null pointer.
Why? This is not a trick question. Think about it.
 
S

Sheldon Simms

Peter said:
...
Just a little finer maybe...

0 #include <stdlib.h>
1
2 typedef struct mystr {
3 struct mystr *p;
4 int i[10];
5 } my_str;
6
7 int main(void) {
8 my_str *use;
9 use = malloc( sizeof *use );
10 use->i[0] = 3333;
11 use->p = malloc( sizeof *use->p );
12 use->p->i[0] = 4444;
13
14 free( use->p );
15 free( use );
16 return 0;
17 }

You should always check whether or not malloc returns a null pointer.
Why? This is not a trick question. Think about it.

Let me try.

By 7.20.3.3.3, malloc may return a null pointer.

By 6.3.2.3.3, a null pointer is guaranteed to compare unequal to a
pointer to any object. Therefore, a null pointer points at no
object.

By 6.5.2.3.4, the value of a -> expression is that of the member
(named by the identifier after the ->) of the object to which the
postfix expression before -> points.

If, after line 9, use is a null pointer, it points at no object and
the expression use->i therefore has undefined value and the attempt
to build the sum (use->i + 0) (as in 6.5.2.1.2) results in undefined
behavior.
 
J

Joe Wright

Sheldon said:
Peter said:
...
Just a little finer maybe...

0 #include <stdlib.h>
1
2 typedef struct mystr {
3 struct mystr *p;
4 int i[10];
5 } my_str;
6
7 int main(void) {
8 my_str *use;
9 use = malloc( sizeof *use );
10 use->i[0] = 3333;
11 use->p = malloc( sizeof *use->p );
12 use->p->i[0] = 4444;
13
14 free( use->p );
15 free( use );
16 return 0;
17 }

You should always check whether or not malloc returns a null pointer.
Why? This is not a trick question. Think about it.

Let me try.

By 7.20.3.3.3, malloc may return a null pointer.

By 6.3.2.3.3, a null pointer is guaranteed to compare unequal to a
pointer to any object. Therefore, a null pointer points at no
object.

By 6.5.2.3.4, the value of a -> expression is that of the member
(named by the identifier after the ->) of the object to which the
postfix expression before -> points.

If, after line 9, use is a null pointer, it points at no object and
the expression use->i therefore has undefined value and the attempt
to build the sum (use->i + 0) (as in 6.5.2.1.2) results in undefined
behavior.

OK Sheldon. Right you are.

Let me appologise to you and the group for lame humour. My point was
that the simple example program was not meant to do anything useful
except to make the use of pointers a little clearer. Including malloc()
error checking would add lots of code without contributing to the
exposition of pointer usage.

In practice, almost all of my programs check the return value of
malloc() and friends something like this..

if ((ptr = malloc( N * sizeof *ptr )) == NULL)
fputs("Malloc Failed\n", stderr), exit(EXIT_FAILURE);

...but I have yet to see it fail unexpectedly. Ever. In twenty years! I
know this is annecdotal how about the rest of you?
 
K

Kevin Easton

Joe Wright said:
In practice, almost all of my programs check the return value of
malloc() and friends something like this..

if ((ptr = malloc( N * sizeof *ptr )) == NULL)
fputs("Malloc Failed\n", stderr), exit(EXIT_FAILURE);

..but I have yet to see it fail unexpectedly. Ever. In twenty years! I
know this is annecdotal how about the rest of you?

If you use an environment that supports user resource limits, try this
command (bourne shell syntax):

ulimit -Sv 4096

- Kevin.
 
S

Steve Zimmerman

Kevin said:
If you use an environment that supports user resource limits, try this
command (bourne shell syntax):

ulimit -Sv 4096

- Kevin.

How much do I owe you guys? :) Seriously, these are great answers.
Thank you!

--Steve Zimmerman


################ Experiment 7 (malloc) #####################

#include <stdio.h>
#include <stdlib.h>

int main()
{
char *h = NULL;
char *g;

g = malloc(30);

if (h == NULL)
fprintf(stderr, "No memory allocation\n");
else
printf("Successful memory allocation\n");

free(g);

return 0;
}

Output: No memory allocation

############### Experiment 8 (malloc) ##########################

#include <stdio.h>
#include <stdlib.h>

int main()
{
char *ptr;

/* The following four lines are copyright (c) Joe Wright. */

if ((ptr = malloc( 30 * sizeof *ptr )) == NULL) {
fputs ("Malloc failed\n", stderr);
exit(EXIT_FAILURE);
}

else {
fputs ("Malloc succeeded\n", stdout);
exit(EXIT_SUCCESS);
}
}

Output: Malloc succeeded
 

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

Similar Threads

Adding adressing of IPv6 to program 1
Array of structs function pointer 10
Organization Assignment in C programming 0
Command Line Arguments 0
malloc 40
Linux: using "clone3" and "waitid" 0
Fibonacci 0
URGENT 1

Members online

Forum statistics

Threads
474,079
Messages
2,570,573
Members
47,204
Latest member
MalorieSte

Latest Threads

Top