473,394 Members | 1,697 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,394 software developers and data experts.

trying to make my "fillvalues" function work...

Hi,

I'm trying to move a matlab program into c language. For those who knows
matlab, this is the line I want to program in c:

hx(1:nx,1:ny) = 0; % nx=10, ny=10

It works on a 2-dimensional array (size is 10*10), setting all the
values inside the 10*10 matrix to zero. My C-function looks like this:
void fillinnumbers(int fillvalue, int startx, int stopx, int starty, int
stopy, int array[][])
{
for(i=startx; i<=stopx; i++)
{
for(j=starty; j<=stopy; j++)
{
array[i][j] = fillvalue;
}
}
}
So, taken the above example: fillvalue = 0, startx = 1, stopx = nx = 10,
starty = 1, stopy = ny = 10, array[][] is the pointer... Now, the
problem is that I'm a C newbie so I there's something wrong with the
array[][] thing, I think...

In my C-program I tried:

fillinnumbers(3, 1, nx, 1, ny, array);

I defined array as: array[nx+1][ny+1]

But using MSVS 2005, I get the following error: "error C2087: 'array' :
missing subscript" - the error points to the line containing the
function declaration: "void fillinnumbers(int fillvalue,.... etc"

And a lot of warnings: "warning C4048: different array subscripts : 'int
(*)[1]' and 'int [11][11]" in each line where I try to call my function
such as in the line containing: "fillinnumbers(3, 1, nx, 1, ny, array);"

I'm not so experienced with C programming, so any help will be greatly
appreciated...
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Feb 26 '06 #1
42 3070
In article <29************@news.tdc.dk>,
=?ISO-8859-1?Q?Martin_J=F8rgensen?= <un*********@spam.jay.net> wrote:

int array[][]

You cannot declare an array like that in C.

There are different kinds of multi-dimensional arrays in C90.

One of them is a block of consequative memory addresses. In order
for C to be able to find the proper location in that block, it
needs to know what maximum size was for all of the dimensions except
the last, as it needs to do the equivilent of
(i-1)*maxfirstdim + (j-1) in order to find the offset from the
beginning of the block of memory. But C doesn't record that dimensional
information as a property of pointers that get passed around, so
when you pass one of these kinds of arrays into another routine,
that other routine has to have a declaration of the array size.

In C90, it is not possible to pass in the size of a multidimensional
array and have a declaration that varies with the passed size.

In C99, the capability to do that was added. But in the context
of your routine, you would need an additional parameter to indicate
the maximum dimension, as your stopx variable is used to indicate
the maximum subscript of the the block that should be filled
rather than the maximum subscript that is possible for the array.
The other major kind of multi-dimensional array is to have each
level of the array -except- the last be a vector (one-dimensional
array) of pointers to objects of the next lower dimensionality,
until finally the second-last dimension is a vector of pointers
to values. There is more than one way to declare such an object
within a parameter list; some people would use, e.g.,
int **array
Using this array in the code would still look exactly the same,
array[i][j]
but it would mean something completely different than in the first
kind of array: it would mean to access the i'th location from
the beginning of the location named array, and that that location
should be used as a pointer to a block of memory, which you
would then take the j'th element of. When you use this kind of
multi-dimensional array, it is not necessary for functions to
know ahead of time what the maximum sizes are for each dimension --
but it also means that the actual memory used to store the array
values is -likely- not a plain block of storage (since pointers
might point all over the place in memory.)
--
"No one has the right to destroy another person's belief by
demanding empirical evidence." -- Ann Landers
Feb 26 '06 #2
Walter Roberson wrote:
In article <29************@news.tdc.dk>,
=?ISO-8859-1?Q?Martin_J=F8rgensen?= <un*********@spam.jay.net> wrote: -snip-
to values. There is more than one way to declare such an object
within a parameter list; some people would use, e.g.,
int **array
Using this array in the code would still look exactly the same,
array[i][j]
but it would mean something completely different than in the first
kind of array: it would mean to access the i'th location from
the beginning of the location named array, and that that location
should be used as a pointer to a block of memory, which you
would then take the j'th element of. When you use this kind of
Ok... Do I have to use malloc or something? Because I'm not really into
that function yet...
multi-dimensional array, it is not necessary for functions to
know ahead of time what the maximum sizes are for each dimension --
but it also means that the actual memory used to store the array
values is -likely- not a plain block of storage (since pointers
might point all over the place in memory.)


Ok... Perhaps somebody could post a working example, that I could learn
from? I understand what you write, but I'm just not sure if I know how
to program it...

Okay, I assume in the beginning of the program, I would declare:

array** int

Now, I "stole/borrowed" something from another code - perhaps I can use
this (I don't even know if this is necessary?):

doublearray = (double**) malloc((size_t) 2*(sizeof(double*)));

for(i=0;i<2;i++)
{
doublearray[i] = (double*) malloc((size_t) 1700*(sizeof(double)));
}

Now since I will also be using my "fillvalues" function on integers I
assume I just replace the word "double" in the above with "int". I know
that the above works on a 1700*2 array, so if I should modify it to
10*10 then I guess I just change the number 2->10 and 1700->10?
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Feb 26 '06 #3

"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:dh************@news.tdc.dk...
Walter Roberson wrote:
In article <29************@news.tdc.dk>,
=?ISO-8859-1?Q?Martin_J=F8rgensen?= <un*********@spam.jay.net> wrote:

-snip-
to values. There is more than one way to declare such an object
within a parameter list; some people would use, e.g.,
int **array
Using this array in the code would still look exactly the same,
array[i][j]
but it would mean something completely different than in the first
kind of array: it would mean to access the i'th location from
the beginning of the location named array, and that that location
should be used as a pointer to a block of memory, which you
would then take the j'th element of. When you use this kind of


Ok... Do I have to use malloc or something? Because I'm not really into
that function yet...
multi-dimensional array, it is not necessary for functions to
know ahead of time what the maximum sizes are for each dimension --
but it also means that the actual memory used to store the array
values is -likely- not a plain block of storage (since pointers
might point all over the place in memory.)


Ok... Perhaps somebody could post a working example, that I could learn
from? I understand what you write, but I'm just not sure if I know how
to program it...

Okay, I assume in the beginning of the program, I would declare:

array** int

Now, I "stole/borrowed" something from another code - perhaps I can use
this (I don't even know if this is necessary?):

doublearray = (double**) malloc((size_t) 2*(sizeof(double*)));

for(i=0;i<2;i++)
{
doublearray[i] = (double*) malloc((size_t) 1700*(sizeof(double)));
}

Now since I will also be using my "fillvalues" function on integers I
assume I just replace the word "double" in the above with "int". I know
that the above works on a 1700*2 array, so if I should modify it to
10*10 then I guess I just change the number 2->10 and 1700->10?

In relation to your original code, replace 2 by (nx+1) and 1700 by (ny+1).
You've got irrelevant complications here because of the change of subscript
base from 1 to 0. You can drop the casts.
That scheme is most useful when the rows are strings of varying length,
since you can set the length of each row separately. This is a simpler C90
version for uniform rows:

/* prototype */
void fillinnumbers(int, int, int, int, int, int **);

/* definition */
void fillinnumbers(int fillvalue, int startx, int stopx, int starty, int
stopy, int **array)
{
for(i=startx; i<=stopx; i++)
for(j=starty; j<=stopy; j++)
array[i][j] = fillvalue;
}

/* caller */
int **array = malloc((nx+1)*sizeof(int*));
array[0] = malloc((nx+1)*(ny+1)*sizeof(int));
for (i = 1; i < nx+1 ;i++)
array[i] = array[i-1] + ny+1; /* save start address of each row */
fillinnumbers(3, 1, nx, 1, ny, array);
free(array[0]);
free(array);

Or, you can just do the subscript arithmetic on the fly as required, instead
of storing the row addresses. Think of the "rows" as being segments of a
long one-dimensional array. Note that you have to pass the width around to
wherever subscript arithmetic is needed

/* prototype */
void fillinnumbers(int, int, int, int, int, int, int *);

/* definition */
void fillinnumbers(int fillvalue, int startx, int stopx, int starty, int
stopy, int ncols, int *a)
{
for(i=startx; i<=stopx; i++)
{
int *array_i = a + i*ncols;
for(j=starty; j<=stopy; j++)
array_i[j] = fillvalue;
}
}

/* caller */
int *p = malloc((nx+1)*(ny+1)*sizeof(int));
fillinnumbers(3, 1, nx, 1, ny, ny+1, p);
free(p);

But you don't need to do any of that. Your compiler has the variable-length
array support from C99. This must be everybody's favourite improvement, but
the advantage will never be realised if everybody insists on making their
code back-portable to C90 for ever.

In C99 all you need is an extra parameter and a bit of clever syntax:

/* prototype */
void fillinnumbers(int, int, int, int, int, int, int array[][*]);

/* definition */
void fillinnumbers(int fillvalue, int startx, int stopx, int starty, int
stopy, int ncols, int array[][ncols])
{
for(i=startx; i<=stopx; i++)
for(j=starty; j<=stopy; j++)
array[i][j] = fillvalue;
}

/* caller */
int array[nx+1][ny+1];
fillinnumbers(3, 1, nx, 1, ny, ny+1, array);

Feb 26 '06 #4
Robin Haigh wrote:
"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:dh************@news.tdc.dk... -snip-
That scheme is most useful when the rows are strings of varying length,
since you can set the length of each row separately. This is a simpler C90
version for uniform rows:

/* prototype */
void fillinnumbers(int, int, int, int, int, int **);

/* definition */
void fillinnumbers(int fillvalue, int startx, int stopx, int starty, int
stopy, int **array)
{
for(i=startx; i<=stopx; i++)
for(j=starty; j<=stopy; j++)
array[i][j] = fillvalue;
}

/* caller */
int **array = malloc((nx+1)*sizeof(int*));
array[0] = malloc((nx+1)*(ny+1)*sizeof(int));
for (i = 1; i < nx+1 ;i++)
array[i] = array[i-1] + ny+1; /* save start address of each row */
fillinnumbers(3, 1, nx, 1, ny, array);
free(array[0]);
free(array);
Damn... Having spent 4 hours or so on this I think I made a program
using the above that works... But I would like to debug it using MSVS
2005 and found that array points to 0x003a4d58. I then click the + sign
and it shows me a value of 0x003a4db0. There's yet another +-sign so I
click on it and find the value -842150451. I don't know quite how to
interpret this since I've never worked with 2D-arrays like this so
please bear over with me and let me know how to understand these memory
numbers...

Since this is a 2D-array what's the easist way of seeing the memory
content at location array[2][2] for instance? Might be there's some
hand-calculation involved? I guess I'll have to do something like
0x003a4d58 + 2 rows + 2 columns and watch that memory address, right?
Or, you can just do the subscript arithmetic on the fly as required, instead
of storing the row addresses. Think of the "rows" as being segments of a
long one-dimensional array. Note that you have to pass the width around to
wherever subscript arithmetic is needed

/* prototype */
void fillinnumbers(int, int, int, int, int, int, int *);

/* definition */
void fillinnumbers(int fillvalue, int startx, int stopx, int starty, int
stopy, int ncols, int *a)
{
for(i=startx; i<=stopx; i++)
{
int *array_i = a + i*ncols;
for(j=starty; j<=stopy; j++)
array_i[j] = fillvalue;
}
}

/* caller */
int *p = malloc((nx+1)*(ny+1)*sizeof(int));
fillinnumbers(3, 1, nx, 1, ny, ny+1, p);
free(p);
That looks like the most complicated/confusing method to me, but I also
read that it's possible to transfer a 2D-array to a 1D-array...
But you don't need to do any of that. Your compiler has the variable-length
array support from C99. This must be everybody's favourite improvement, but
the advantage will never be realised if everybody insists on making their
code back-portable to C90 for ever.

In C99 all you need is an extra parameter and a bit of clever syntax:

/* prototype */
void fillinnumbers(int, int, int, int, int, int, int array[][*]);

/* definition */
void fillinnumbers(int fillvalue, int startx, int stopx, int starty, int
stopy, int ncols, int array[][ncols])
{
for(i=startx; i<=stopx; i++)
for(j=starty; j<=stopy; j++)
array[i][j] = fillvalue;
}

/* caller */
int array[nx+1][ny+1];
fillinnumbers(3, 1, nx, 1, ny, ny+1, array);


This was actually the first thing I tried... I wanted to try this last
thing first, because it seemed very easy. But I got these for the line
"void fillinnumbers(int fillvalue, int startx, int"...

error C2057: expected constant expression
error C2466: cannot allocate an array of constant size 0
error C2087: 'array' : missing subscript

Therefore I tried your first solution and it seems to work (I inserted
prinft(" -> %i ", array[i][j]); in a new function very similary to the
fillinnumbers function...
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Feb 26 '06 #5
Robin Haigh wrote:
"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:dh************@news.tdc.dk...
Walter Roberson wrote:

-snip-

Damn.... Am i just blind or something... Why the hell is MS VS 2005
complaining about this code:

---------

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

int main(void)
{
printf("ADI Method is used.\n");

int **array = malloc((nx+1)*sizeof(int*));

return 0; /* ANSI-C requires main to return integer */

} /* End of main program */

-----

error C2143: syntax error : missing ';' before 'type' in the line: "int
**array = malloc((nx+1)*sizeof(int*));" - but there *IS* a semicolon... ???
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Feb 26 '06 #6
Martin Jørgensen said:
Robin Haigh wrote:
"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:dh************@news.tdc.dk...
Walter Roberson wrote:
-snip-

Damn.... Am i just blind or something... Why the hell is MS VS 2005
complaining about this code:

---------

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

int main(void)
{
printf("ADI Method is used.\n");


That's code...

int **array = malloc((nx+1)*sizeof(int*));


....and that's a declaration, which follows the code.

Solution: move (or remove) the printf.
--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Feb 26 '06 #7
On 2006-02-26, Richard Heathfield <in*****@invalid.invalid> wrote:
Martin Jørgensen said:
Robin Haigh wrote:
"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:dh************@news.tdc.dk...

Walter Roberson wrote:

-snip-

Damn.... Am i just blind or something... Why the hell is MS VS 2005
complaining about this code:

---------

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

int main(void)
{
printf("ADI Method is used.\n");


That's code...

int **array = malloc((nx+1)*sizeof(int*));


...and that's a declaration, which follows the code.

Solution: move (or remove) the printf.


Isn't that very compiler/C version specific?

I've been swapping between languages so much recently that I totally
forgot about limitations on where and when you can declare
variables. Whats the C standard these days?

--
Remove evomer to reply
Feb 26 '06 #8
Martin Jørgensen wrote:

<snip>
Damn.... Am i just blind or something... Why the hell is MS VS 2005
complaining about this code:

---------

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

int main(void)
{
printf("ADI Method is used.\n");

int **array = malloc((nx+1)*sizeof(int*));

return 0; /* ANSI-C requires main to return integer */

} /* End of main program */

-----

error C2143: syntax error : missing ';' before 'type' in the line: "int
**array = malloc((nx+1)*sizeof(int*));" - but there *IS* a semicolon... ???


Perhaps it is complaining because in C89 (the only C standard MS VS any
version supports) you can't mix declarations and statements.

Of course, the error message it is giving you is completely unhelpful.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Feb 26 '06 #9
Flash Gordon wrote:
Martin Jørgensen wrote:

<snip>
Damn.... Am i just blind or something... Why the hell is MS VS 2005
complaining about this code:

---------

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

int main(void)
{
printf("ADI Method is used.\n");

int **array = malloc((nx+1)*sizeof(int*));

return 0; /* ANSI-C requires main to return integer */

} /* End of main program */

-----

error C2143: syntax error : missing ';' before 'type' in the line:
"int **array = malloc((nx+1)*sizeof(int*));" - but there *IS* a
semicolon... ???

Perhaps it is complaining because in C89 (the only C standard MS VS any
version supports) you can't mix declarations and statements.

Of course, the error message it is giving you is completely unhelpful.


OMFG! What a fucking psychopathic error message... I spend hours looking
for a missing semi-colon and couldn't find it... But now it seems to
work, thanks...

BTW: I'm wondering... Each time I use malloc(), shouldn't I also do a
check like this:

if (ptd == NULL)
{
puts("Memory allocation failure. Bye\n");
exit(EXIT_FAILURE);
}

?

Because I didn't use it anywhere and now I got about 8-10 malloc() in my
new program (which partly has been converted from Matlab)...
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Feb 26 '06 #10

"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:5e************@news.tdc.dk...
Robin Haigh wrote:
"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:dh************@news.tdc.dk...
Walter Roberson wrote:

-snip-

Damn.... Am i just blind or something... Why the hell is MS VS 2005
complaining about this code:

---------

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

int main(void)
{
printf("ADI Method is used.\n");

int **array = malloc((nx+1)*sizeof(int*));

return 0; /* ANSI-C requires main to return integer */

} /* End of main program */

-----

error C2143: syntax error : missing ';' before 'type' in the line: "int
**array = malloc((nx+1)*sizeof(int*));" - but there *IS* a semicolon...
???


Ok the first thing I can see is that you need to declare int **array =
malloc((nx+1)*sizeof(int*));
before the printf line like so;

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

int main(void)
{
int **array = malloc((nx+1)*sizeof(int*));

printf("ADI Method is used.\n");

return 0; /* ANSI-C requires main to return integer */
} /* End of main program */

After that you'll get an a different error which I think you should be able
to fix on your own. A clue... What is the value of nx?

Good Luck

--
MrG{DRGN}
Feb 26 '06 #11
Martin Jørgensen schrieb:
<snip>
BTW: I'm wondering... Each time I use malloc(), shouldn't I also do a
check like this:
I assume ptd contains the result of a malloc() call.
if (ptd == NULL)
{
puts("Memory allocation failure. Bye\n");
Usually, it is a good idea to put error messages to stderr, i.e.
fputs("Your error message here\n", stderr);
as this gives the user the choice whether to suppress or redirect
output and/or errors (i.e. stdout and/or stderr).
exit(EXIT_FAILURE);
This is the most drastic of all possible error treatments.
It may be better to
- try to salvage the situation by trying to allocate less memory
- terminate orderly, if that does not work/is not possible; this
includes writing out the output as far as it is ready, freeing
all resources used by your program.
- ... (whatever you can come up with, maybe even switching to a
less memory but more time consuming method). }

?

Because I didn't use it anywhere and now I got about 8-10 malloc() in my
new program (which partly has been converted from Matlab)...


By all means: Yes!
Always check the return value of malloc() and introduce reasonable
error handling. Check this error handling by demanding absurdly
much memory or changing if (ptd == NULL) to if (0 && ptd == NULL).
Writing out an error message and aborting is often what you see
in newsgroups but it is most of the time insufficient in real life.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Feb 26 '06 #12
On 2006-02-26, Michael Mair <Mi**********@invalid.invalid> wrote:
Martin Jørgensen schrieb:
<snip>
BTW: I'm wondering... Each time I use malloc(), shouldn't I also do a
check like this:
I assume ptd contains the result of a malloc() call.

if (ptd == NULL)
{
puts("Memory allocation failure. Bye\n");


Usually, it is a good idea to put error messages to stderr, i.e.
fputs("Your error message here\n", stderr);
as this gives the user the choice whether to suppress or redirect
output and/or errors (i.e. stdout and/or stderr).
exit(EXIT_FAILURE);


This is the most drastic of all possible error treatments.
It may be better to
- try to salvage the situation by trying to allocate less memory
- terminate orderly, if that does not work/is not possible; this
includes writing out the output as far as it is ready, freeing
all resources used by your program.


It can be argued that good program design includes causing exit() result
in an orderly termination - this can be accomplished, to some extent, by
setting up atexit() handlers.
- ... (whatever you can come up with, maybe even switching to a
less memory but more time consuming method).


Or simply failing your own function and letting the caller deal with it.
this is what fopen() does, for example, on many systems, if it fails to
allocate memory for a FILE structure.
Feb 26 '06 #13
Richard G. Riley wrote:

<snip intermixing declarations and statements and an error reported by
MS VS 2005>
Isn't that very compiler/C version specific?

I've been swapping between languages so much recently that I totally
forgot about limitations on where and when you can declare
variables. Whats the C standard these days?


It's dependant on the version of the standard implemented by the
compiler (or whether it allows it as an extension). The ability to
intermix statements and declarations was added in C99 but MS has decided
not to implement C99.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Feb 26 '06 #14

"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:aq************@news.tdc.dk...
Robin Haigh wrote:
"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:dh************@news.tdc.dk... -snip-
That scheme is most useful when the rows are strings of varying length,
since you can set the length of each row separately. This is a simpler C90 version for uniform rows:

/* prototype */
void fillinnumbers(int, int, int, int, int, int **);

/* definition */
void fillinnumbers(int fillvalue, int startx, int stopx, int starty, int
stopy, int **array)
{
for(i=startx; i<=stopx; i++)
for(j=starty; j<=stopy; j++)
array[i][j] = fillvalue;
}

/* caller */
int **array = malloc((nx+1)*sizeof(int*));
array[0] = malloc((nx+1)*(ny+1)*sizeof(int));
for (i = 1; i < nx+1 ;i++)
array[i] = array[i-1] + ny+1; /* save start address of each row */ fillinnumbers(3, 1, nx, 1, ny, array);
free(array[0]);
free(array);


Damn... Having spent 4 hours or so on this I think I made a program
using the above that works... But I would like to debug it using MSVS
2005 and found that array points to 0x003a4d58. I then click the + sign
and it shows me a value of 0x003a4db0. There's yet another +-sign so I
click on it and find the value -842150451. I don't know quite how to
interpret this since I've never worked with 2D-arrays like this so
please bear over with me and let me know how to understand these memory
numbers...


You've allocated two blocks of memory. The first is at 3a4d58 and will hold
a pointer vector with a pointer for each row, so its size is
number-of-rows*size-of-pointer.

The second is at 3a4db0 and holds the matrix, so its size is
rows*cols*sizeof(int).

The rows of the matrix are laid out one after the other, so
start address of row 0 = start address of block = 3a4db0
start address of row 1 = 3a4db0 + size of 1 row
where size of 1 row = number of columns * sizeof(int)
start address of row 2 = 3a4db0 + size of 2 rows (= start address of row 1
+ size of 1 row)
etc

and these addresses are stored in the vector as array[0], array[1],
array[2], etc

So the debugger shows
array = address of vector = 3a4d58
*array = array[0] = element 0 of vector = start address of row 0 = 3a4db0
**array = array[0][0] = -842150451 = uninitialised int data.
fillinnumbers() starts at array[1][1], so array[0][0] never gets used.


Since this is a 2D-array what's the easist way of seeing the memory
content at location array[2][2] for instance?
Watching array[2][2] works for me, but only after array[2] is assigned a
value.

If you've got 11 columns, array[0][2*11+2] should be equivalent.

Might be there's some
hand-calculation involved? I guess I'll have to do something like
0x003a4d58 + 2 rows + 2 columns and watch that memory address, right?
You'd be starting from the base of the matrix block, so for 11 columns it
would be
3a4db0 + (2*11 + 2)*sizeof(int)



[snip]
But you don't need to do any of that. Your compiler has the variable-length array support from C99. This must be everybody's favourite improvement, but the advantage will never be realised if everybody insists on making their code back-portable to C90 for ever.

In C99 all you need is an extra parameter and a bit of clever syntax:

/* prototype */
void fillinnumbers(int, int, int, int, int, int, int array[][*]);

/* definition */
void fillinnumbers(int fillvalue, int startx, int stopx, int starty, int
stopy, int ncols, int array[][ncols])
{
for(i=startx; i<=stopx; i++)
for(j=starty; j<=stopy; j++)
array[i][j] = fillvalue;
}

/* caller */
int array[nx+1][ny+1];
fillinnumbers(3, 1, nx, 1, ny, ny+1, array);


This was actually the first thing I tried... I wanted to try this last
thing first, because it seemed very easy. But I got these for the line
"void fillinnumbers(int fillvalue, int startx, int"...

error C2057: expected constant expression
error C2466: cannot allocate an array of constant size 0
error C2087: 'array' : missing subscript


Since your compiler accepts
int array[nx+1][ny+1];
I assumed it had full support for VLAs, but perhaps it doesn't.
--
RSH

Feb 27 '06 #15
Michael Mair wrote:
Martin Jørgensen schrieb:
<snip>
BTW: I'm wondering... Each time I use malloc(), shouldn't I also do a
check like this:

I assume ptd contains the result of a malloc() call.


Yep.
if (ptd == NULL)
{
puts("Memory allocation failure. Bye\n");

Usually, it is a good idea to put error messages to stderr, i.e.
fputs("Your error message here\n", stderr);
as this gives the user the choice whether to suppress or redirect
output and/or errors (i.e. stdout and/or stderr).


Since I've got a lot of malloc's (8-10) perhaps I could make a function:

checkPtr_error(%s location, %p pointer)
{
if (pointer == NULL)
{
fputs("Memory allocation failure (%s). Bye\n", location, stderr);
}
}

So I have something like:
int **array = malloc((nx+1)*sizeof(int*));
checkPtr_error("array", &array)
int **var1 = malloc((nx+1)*sizeof(int*));
checkPtr_error("var1", &var1)
int **var2 = malloc((nx+1)*sizeof(int*));
checkPtr_error("var2", &var2)
int **doubleptr = malloc((nx+1)*sizeof(double*));
checkPtr_error("doubleptr", &doubleptr)
etc.

The above is untested, but using a checkPtr_error function could save me
for typing some code, right?
exit(EXIT_FAILURE);

This is the most drastic of all possible error treatments.
It may be better to
- try to salvage the situation by trying to allocate less memory
- terminate orderly, if that does not work/is not possible; this
includes writing out the output as far as it is ready, freeing
all resources used by your program.
- ... (whatever you can come up with, maybe even switching to a
less memory but more time consuming method).


Ok... I'll see what I can do.
}

?

Because I didn't use it anywhere and now I got about 8-10 malloc() in
my new program (which partly has been converted from Matlab)...

By all means: Yes!
Always check the return value of malloc() and introduce reasonable
error handling. Check this error handling by demanding absurdly
much memory or changing if (ptd == NULL) to if (0 && ptd == NULL).
Writing out an error message and aborting is often what you see
in newsgroups but it is most of the time insufficient in real life.


Ok. I'll look at the other messages when I get home in the evening...
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Feb 27 '06 #16
Martin Jørgensen wrote:
Michael Mair wrote: -snip-
Since I've got a lot of malloc's (8-10) perhaps I could make a function:

checkPtr_error(%s location, %p pointer)
{
if (pointer == NULL)
{
fputs("Memory allocation failure (%s). Bye\n", location, stderr);
}
}

So I have something like:
int **array = malloc((nx+1)*sizeof(int*));
checkPtr_error("array", &array)
int **var1 = malloc((nx+1)*sizeof(int*));
checkPtr_error("var1", &var1)
int **var2 = malloc((nx+1)*sizeof(int*));
checkPtr_error("var2", &var2)
int **doubleptr = malloc((nx+1)*sizeof(double*));
checkPtr_error("doubleptr", &doubleptr)
etc.

The above is untested, but using a checkPtr_error function could save me
for typing some code, right?

Well, could I do that? Does it work!?!?! Or should I forget about it?
-snip-
By all means: Yes!
Always check the return value of malloc() and introduce reasonable
error handling. Check this error handling by demanding absurdly
much memory or changing if (ptd == NULL) to if (0 && ptd == NULL).


Why do you have a 0 in here: if(0 && ptd == NULL) instead of just if(ptd
== NULL) ?
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Feb 27 '06 #17
Martin Jørgensen schrieb:
Martin Jørgensen wrote:
Michael Mair wrote:


-snip-
Since I've got a lot of malloc's (8-10) perhaps I could make a function:

checkPtr_error(%s location, %p pointer)
{
if (pointer == NULL)
{
fputs("Memory allocation failure (%s). Bye\n", location, stderr);
}
}

So I have something like:
int **array = malloc((nx+1)*sizeof(int*));
checkPtr_error("array", &array)
int **var1 = malloc((nx+1)*sizeof(int*));
checkPtr_error("var1", &var1)
int **var2 = malloc((nx+1)*sizeof(int*));
checkPtr_error("var2", &var2)
int **doubleptr = malloc((nx+1)*sizeof(double*));
checkPtr_error("doubleptr", &doubleptr)
etc.

The above is untested, but using a checkPtr_error function could save
me for typing some code, right?


Well, could I do that? Does it work!?!?! Or should I forget about it?


You could but I do not see much benefit.
Generating a good "location" may involve __FILE__, __LINE__ (, __func__
in C99), iteration count or something else to indicate "when and where"
allocation fails, i.e. you rather want to check for null pointers
_before_ generating "location".
However, wrapping the actual output into a separate function _can_
be a good idea. I.e.
if (NULL == ptr) {
/* generate location */
....
printErrAllocation(location, ptr);
}
By all means: Yes!
Always check the return value of malloc() and introduce reasonable
error handling. Check this error handling by demanding absurdly
much memory or changing if (ptd == NULL) to if (0 && ptd == NULL).


Why do you have a 0 in here: if(0 && ptd == NULL) instead of just if(ptd
== NULL) ?


I did not think twice about it ;-(
Think
1 || ptd == NULL
(or "0 && ptd != NULL" for the other way round) instead.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Feb 27 '06 #18
Robin Haigh wrote:
"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:aq************@news.tdc.dk... -snip-

First: Thanks writing such an excellent explanation.
Damn... Having spent 4 hours or so on this I think I made a program
using the above that works... But I would like to debug it using MSVS
2005 and found that array points to 0x003a4d58. I then click the + sign
and it shows me a value of 0x003a4db0. There's yet another +-sign so I
click on it and find the value -842150451. I don't know quite how to
interpret this since I've never worked with 2D-arrays like this so
please bear over with me and let me know how to understand these memory
numbers...

You've allocated two blocks of memory. The first is at 3a4d58 and will hold
a pointer vector with a pointer for each row, so its size is
number-of-rows*size-of-pointer.


Yeah, that is this one, right?

"int **number = malloc((nx+1)*sizeof(int*));"

The two stars ** means that it is a pointer to a pointer (to an
integer), right?

I can easily picture myself a 1-dimensional array pointer, having seen
such one in a figure in my C-programming book...

I think I would understand it more easily if there exists a graphical
explanation somewhere on the net - perhaps somebody has a link?
The second is at 3a4db0 and holds the matrix, so its size is
rows*cols*sizeof(int).
That is a "single" pointer to some integers like here, I assume:

number[0] = malloc((nx+1)*(ny+1)*sizeof(int));
The rows of the matrix are laid out one after the other, so
start address of row 0 = start address of block = 3a4db0
start address of row 1 = 3a4db0 + size of 1 row
where size of 1 row = number of columns * sizeof(int)
start address of row 2 = 3a4db0 + size of 2 rows (= start address of row 1
+ size of 1 row)
etc
Ok.
and these addresses are stored in the vector as array[0], array[1],
array[2], etc
Let me be sure I understand this:

array[0] = start address of block = 3a4db0
array[1] = array[0] + size of 1 row
array[2] = array[1] + size of 1 row

It that correct or not?
So the debugger shows
array = address of vector = 3a4d58
*array = array[0] = element 0 of vector = start address of row 0 = 3a4db0
**array = array[0][0] = -842150451 = uninitialised int data.
Hmmmmmm. I want to see my 2D-array in the debugger. I now successfully
made a program like this:

count = 0;
for(i=0; i<=nx; i++) /* go through all rows */
{
for(j=0; j<=ny; j++){array[i][j] = ++count;}
printout(0, nx, 0, ny, array);
}

Calling printout gives me the expected values (all are double values):

1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0
8.0, 9.0, 10, 11, 12, 13, 14
15, 16, 17, 18, 19, 20, 21
22, 23, 24, 25, 26, 27, 28
29, 30, 31, 32, 33, 34, 35
36, 37, 38, 39, 40, 41, 42
43, 44, 45, 46, 47, 48, 49

So it works. I just want to be able to debug just by watching things in
memory. Moving my mouse pointer over array gives me (probably new memory
location compared to yesterday):

1) 0x003a4d60. Clicking the "+"-sign gives me:
2) 0x003a4db8. And clicking the "+"-sign again gives me the first array
element:
3) 1.0!

Hooray... My memory dump looks like this:

0x003A4DB8 00 00 00 00 00 00 f0 3f 00 00 00 00 00 00 00 40 00 00
.......?.......@..
0x003A4DCA 00 00 00 00 08 40 00 00 00 00 00 00 10 40 00 00 00 00
......@.......@....
0x003A4DDC 00 00 14 40 00 00 00 00 00 00 18 40 00 00 00 00 00 00
....@.......@......
....
....

That is double. As wrote earlier: I want see my numbers array 1 to 49? I
don't remember if a double value (double pointer?) takes 8 bytes but if
so, I remember that the first value (00 00 00 00 00 00 f0 3f) must be
something like: 3ff0 or something. Please tell me how to convert these
bytes from the memory dump to a memory location...

My guess is that I should look 0x003a4db8 and find out where it points
to (something with 3ff0 - please tell me, I'm not sure). And looking
*there* I hope to find the first array element: 1.0......?

Right or wrong?

I would really appreciate a solution/formula/step-by-step instruction
here, *indeed*. :-)
fillinnumbers() starts at array[1][1], so array[0][0] never gets used.
Since this is a 2D-array what's the easist way of seeing the memory
content at location array[2][2] for instance?

Watching array[2][2] works for me, but only after array[2] is assigned a
value.


Doesn't work here. I can only see the first value "1.0".
If you've got 11 columns, array[0][2*11+2] should be equivalent.
Might be there's some
hand-calculation involved? I guess I'll have to do something like
0x003a4d58 + 2 rows + 2 columns and watch that memory address, right?

You'd be starting from the base of the matrix block, so for 11 columns it
would be
3a4db0 + (2*11 + 2)*sizeof(int)


I'll have to get back to that and try it (understand) it later :-)
But you don't need to do any of that. Your compiler has the
variable-length
array support from C99. This must be everybody's favourite improvement,
but
the advantage will never be realised if everybody insists on making
their
code back-portable to C90 for ever.

In C99 all you need is an extra parameter and a bit of clever syntax:

/* prototype */
void fillinnumbers(int, int, int, int, int, int, int array[][*]);

/* definition */
void fillinnumbers(int fillvalue, int startx, int stopx, int starty, int
stopy, int ncols, int array[][ncols])
{
for(i=startx; i<=stopx; i++)
for(j=starty; j<=stopy; j++)
array[i][j] = fillvalue;
}

/* caller */
int array[nx+1][ny+1];
fillinnumbers(3, 1, nx, 1, ny, ny+1, array);


This was actually the first thing I tried... I wanted to try this last
thing first, because it seemed very easy. But I got these for the line
"void fillinnumbers(int fillvalue, int startx, int"...

error C2057: expected constant expression
error C2466: cannot allocate an array of constant size 0
error C2087: 'array' : missing subscript

Since your compiler accepts
int array[nx+1][ny+1];
I assumed it had full support for VLAs, but perhaps it doesn't.


nx and ny was not variables. They were #define'd if that makes any
difference...
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Feb 27 '06 #19
Michael Mair wrote:
Martin Jørgensen schrieb: -snip-
checkPtr_error(%s location, %p pointer)
{
if (pointer == NULL)
{
fputs("Memory allocation failure (%s). Bye\n", location, stderr);
}
}

So I have something like:
int **array = malloc((nx+1)*sizeof(int*));
checkPtr_error("array", &array)
int **var1 = malloc((nx+1)*sizeof(int*));
checkPtr_error("var1", &var1)
int **var2 = malloc((nx+1)*sizeof(int*));
checkPtr_error("var2", &var2)
int **doubleptr = malloc((nx+1)*sizeof(double*));
checkPtr_error("doubleptr", &doubleptr)
etc.

The above is untested, but using a checkPtr_error function could save
me for typing some code, right?

Well, could I do that? Does it work!?!?! Or should I forget about it?

You could but I do not see much benefit.
Generating a good "location" may involve __FILE__, __LINE__ (, __func__
in C99), iteration count or something else to indicate "when and where"
allocation fails, i.e. you rather want to check for null pointers
_before_ generating "location".


Perhaps a stupid question, but what's those __FILE__, __LINE__ (,
__func__ things?
However, wrapping the actual output into a separate function _can_
be a good idea. I.e.
if (NULL == ptr) {
/* generate location */
....
printErrAllocation(location, ptr);
}


Well, I think you're much more advanced than me when you think about
generating a location... My "location" is just a char-array:

int **array = malloc((nx+1)*sizeof(int*));
checkPtr_error("array", &array)

Here "array" is the "location" and "array" will be printed if this is
the location where memory couldn't be allocated.
By all means: Yes!
Always check the return value of malloc() and introduce reasonable
error handling. Check this error handling by demanding absurdly
much memory or changing if (ptd == NULL) to if (0 && ptd == NULL).

Why do you have a 0 in here: if(0 && ptd == NULL) instead of just
if(ptd == NULL) ?

I did not think twice about it ;-(
Think
1 || ptd == NULL
(or "0 && ptd != NULL" for the other way round) instead.


I might be stupid or too unexperienced with C-programming but I still
don't get that. The following works, right: if (NULL == ptr) {.....}

So doing either:

1 || ptd == NULL

or:

"0 && ptd != NULL"

I don't understand what that does... In the first case: if(1 || ptd ==
NULL) would always give 1, becuase || = logical "or" right? 1 = true, AFAIR.

In the second case: if(0 && ptd != NULL) that would always give 0
because && means logical "and", right?
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Feb 27 '06 #20
Martin Jørgensen <un*********@spam.jay.net> writes:
Michael Mair wrote:
Martin Jørgensen schrieb: Generating a good "location" may involve __FILE__, __LINE__ (, __func__
in C99), iteration count or something else to indicate "when and where"
allocation fails, i.e. you rather want to check for null pointers
_before_ generating "location".


Perhaps a stupid question, but what's those __FILE__, __LINE__ (,
__func__ things?


__FILE__ and __LINE__ are special "macro"-like identifiers that the
preprocessor automatically replaces with the name of the file and the
line number (respectively) in which they appeared. These have been
around forever(?).

There is no "(" thing... Michael was just trying to include the tail
end of the list (consisting of just __func__) into the parentheses.

__func__ is new to C99, and is similar to the other two: the
difference is that it's not handled during preprocessing: it's an
actual variable defined in every function (well, in practice it's only
defined in functions that actually refer to it).

The only practical difference in usage between __FILE__ and __func__
is that you can use __FILE__ with the preprocessor's
string-concatenation feature to do:

fputs(__FILE__ ": this file has sucky code.\n", stderr);

whereas with __func__, since it resolves to an actual object, you have
to do something like:

fprintf(stderr, "%s: this function does, too.\n", __func__);

-Micah
Feb 27 '06 #21
Martin Jørgensen schrieb:
Michael Mair wrote:
Martin Jørgensen schrieb:

checkPtr_error(%s location, %p pointer)
{
if (pointer == NULL)
{
fputs("Memory allocation failure (%s). Bye\n", location, stderr);
}
}

So I have something like:
int **array = malloc((nx+1)*sizeof(int*));
checkPtr_error("array", &array)
int **var1 = malloc((nx+1)*sizeof(int*));
checkPtr_error("var1", &var1)
int **var2 = malloc((nx+1)*sizeof(int*));
checkPtr_error("var2", &var2)
int **doubleptr = malloc((nx+1)*sizeof(double*));
checkPtr_error("doubleptr", &doubleptr)
etc.

The above is untested, but using a checkPtr_error function could
save me for typing some code, right?

Well, could I do that? Does it work!?!?! Or should I forget about it?


You could but I do not see much benefit.
Generating a good "location" may involve __FILE__, __LINE__ (, __func__
in C99), iteration count or something else to indicate "when and where"
allocation fails, i.e. you rather want to check for null pointers
_before_ generating "location".


Perhaps a stupid question, but what's those __FILE__, __LINE__ (,
__func__ things?


__FILE__ and __LINE__ are predefined macro names giving you the
current file and line; you can set the current file/line with the
#line directive. Just look it up in your C text book.
There are other predefined macros for time, to find out whether you
have standard C and if yes, which version etc.
C99 adds __func__, which gives you the name of the current function.
However, wrapping the actual output into a separate function _can_
be a good idea. I.e.
if (NULL == ptr) {
/* generate location */
....
printErrAllocation(location, ptr);
}


Well, I think you're much more advanced than me when you think about
generating a location... My "location" is just a char-array:

int **array = malloc((nx+1)*sizeof(int*));
checkPtr_error("array", &array)

Here "array" is the "location" and "array" will be printed if this is
the location where memory couldn't be allocated.


Nonetheless, there is not much benefit in such a checkPtr_error()
function -- it still does not handle the error nicely. Different
places in your code may give you a chance to salvage your work
or may facilitate terminating orderly or lend themselves to aborting
only.
> By all means: Yes!
> Always check the return value of malloc() and introduce reasonable
> error handling. Check this error handling by demanding absurdly
> much memory or changing if (ptd == NULL) to if (0 && ptd == NULL).

Why do you have a 0 in here: if(0 && ptd == NULL) instead of just
if(ptd == NULL) ?


I did not think twice about it ;-(
Think
1 || ptd == NULL
(or "0 && ptd != NULL" for the other way round) instead.


I might be stupid or too unexperienced with C-programming but I still
don't get that. The following works, right: if (NULL == ptr) {.....}

So doing either:

1 || ptd == NULL

or:

"0 && ptd != NULL"

I don't understand what that does... In the first case: if(1 || ptd ==
NULL) would always give 1, becuase || = logical "or" right? 1 = true,
AFAIR.

In the second case: if(0 && ptd != NULL) that would always give 0
because && means logical "and", right?


Yes. This is what I am talking about: 1 || whatever is always true,
0 && whatever is always false; "whatever" is not evaluated.
I just wanted to illustrate _how_ you can make sure that your
error handling is activated. Writing "1 || " in front of "ptd == NULL"
is nicer than replacing it by "1" as it saves the original expression.
There are more sophisticated ways of going about it, of course,
but allocating a very large amount of memory, e.g. (size_t)-2 bytes,
or switching your error catching ifs to true are good examples.

The main thing is: Test your error handling code. Many people don't
but essentially this is your last line of defense. If you have waited
several days for the result of a lengthy computation and it dies
literally during the last iteration, then you are certainly unhappy
if insufficient error handling eats the result dump or restart data.

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Feb 28 '06 #22
"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:9f************@news.tdc.dk...
I might be stupid or too unexperienced with C-programming but I still
don't get that. The following works, right: if (NULL == ptr) {.....}

So doing either:

1 || ptd == NULL

or:

"0 && ptd != NULL"

I don't understand what that does... In the first case: if(1 || ptd ==
NULL) would always give 1, becuase || = logical "or" right? 1 = true,

AFAIR.

Yes that expression always yields 1, which equals to true in a logical
context. Altering the condition in this way can show you how your error
handling works. That is because the (compound) statement under if will be
executed, which would be executed only in the case of allocation failure
otherwise.
Feb 28 '06 #23
Micah Cowan <mi***@cowan.name> writes:
[...]
__FILE__ and __LINE__ are special "macro"-like identifiers that the
preprocessor automatically replaces with the name of the file and the
line number (respectively) in which they appeared. These have been
around forever(?).


They're not just '"macro"-like identifiers'. They're macros.

--
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.
Feb 28 '06 #24

"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:7f************@news.tdc.dk...

[snip]
(all questions agreed)

Let me be sure I understand this:

array[0] = start address of block = 3a4db0
array[1] = array[0] + size of 1 row
array[2] = array[1] + size of 1 row

It that correct or not?
yes
So the debugger shows
array = address of vector = 3a4d58
*array = array[0] = element 0 of vector = start address of row 0 = 3a4db0 **array = array[0][0] = -842150451 = uninitialised int data.
Hmmmmmm. I want to see my 2D-array in the debugger. I now successfully
made a program like this:

count = 0;
for(i=0; i<=nx; i++) /* go through all rows */
{
for(j=0; j<=ny; j++){array[i][j] = ++count;}
printout(0, nx, 0, ny, array);
}

Calling printout gives me the expected values (all are double values):

1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0
8.0, 9.0, 10, 11, 12, 13, 14
15, 16, 17, 18, 19, 20, 21
22, 23, 24, 25, 26, 27, 28
29, 30, 31, 32, 33, 34, 35
36, 37, 38, 39, 40, 41, 42
43, 44, 45, 46, 47, 48, 49

So it works. I just want to be able to debug just by watching things in
memory. Moving my mouse pointer over array gives me (probably new memory
location compared to yesterday):

1) 0x003a4d60. Clicking the "+"-sign gives me:
2) 0x003a4db8. And clicking the "+"-sign again gives me the first array
element:
3) 1.0!

Hooray... My memory dump looks like this:

0x003A4DB8 00 00 00 00 00 00 f0 3f 00 00 00 00 00 00 00 40 00 00
......?.......@..
0x003A4DCA 00 00 00 00 08 40 00 00 00 00 00 00 10 40 00 00 00 00
.....@.......@....
0x003A4DDC 00 00 14 40 00 00 00 00 00 00 18 40 00 00 00 00 00 00
...@.......@......
...
...

That is double. As wrote earlier: I want see my numbers array 1 to 49? I
don't remember if a double value (double pointer?) takes 8 bytes but if
so, I remember that the first value (00 00 00 00 00 00 f0 3f) must be
something like: 3ff0 or something. Please tell me how to convert these
bytes from the memory dump to a memory location...


These are your doubles that you're looking at. Yes, they are 8 bytes, and
3ff0000000000000 is the internal representation of 1.0 as a double. You
don't have to do anything else to find it -- the trick would be to get it
displayed in a more human-readable display format


My guess is that I should look 0x003a4db8 and find out where it points
to (something with 3ff0 - please tell me, I'm not sure). And looking
*there* I hope to find the first array element: 1.0......?
No, 3a4db8 is the value of array[0], so it's the value of a double*, which
means it's the address of a double. So, when you're looking at the contents
of location 3a4db8, you're looking at the actual double, no more pointers to
follow.
nx and ny was not variables. They were #define'd if that makes any
difference...


It makes all the difference. It means your arrays are fixed size, not
variable, as far as the compiler is concerned. No mallocs required. Going
back to your original code,

void fillinnumbers(int fillvalue, int startx, int stopx, int starty, int
stopy, int array[][])
{
for(i=startx; i<=stopx; i++)
{
for(j=starty; j<=stopy; j++)
{
array[i][j] = fillvalue;
}
}
}

you can fix that just by changing int array[][] to int array[][ny+1]. That
doesn't work in any kind of C if ny is a variable, but if it's a macro for a
constant, no problem.

This code dumps out the internal representations of some 8-byte doubles:

#include <stdio.h>
char hex[] = "0123456789abcdef";
int main (void) {
int i;
double a;
unsigned char *pc;
pc = (unsigned char *)&a;
for ( i = 0 ; i < 50 ; i++ ) {
a = (double)i;
printf("%5.1f %c%c %c%c %c%c %c%c %c%c %c%c %c%c %c%c\n", a,
hex[pc[0] >> 4], hex[pc[0] & 0xf],
hex[pc[1] >> 4], hex[pc[1] & 0xf],
hex[pc[2] >> 4], hex[pc[2] & 0xf],
hex[pc[3] >> 4], hex[pc[3] & 0xf],
hex[pc[4] >> 4], hex[pc[4] & 0xf],
hex[pc[5] >> 4], hex[pc[5] & 0xf],
hex[pc[6] >> 4], hex[pc[6] & 0xf],
hex[pc[7] >> 4], hex[pc[7] & 0xf]);
}
return 0;
}

output:
0.0 00 00 00 00 00 00 00 00
1.0 00 00 00 00 00 00 f0 3f
2.0 00 00 00 00 00 00 00 40
3.0 00 00 00 00 00 00 08 40
4.0 00 00 00 00 00 00 10 40
5.0 00 00 00 00 00 00 14 40
6.0 00 00 00 00 00 00 18 40
7.0 00 00 00 00 00 00 1c 40
8.0 00 00 00 00 00 00 20 40
9.0 00 00 00 00 00 00 22 40
10.0 00 00 00 00 00 00 24 40
11.0 00 00 00 00 00 00 26 40
12.0 00 00 00 00 00 00 28 40
13.0 00 00 00 00 00 00 2a 40
14.0 00 00 00 00 00 00 2c 40
15.0 00 00 00 00 00 00 2e 40
16.0 00 00 00 00 00 00 30 40
17.0 00 00 00 00 00 00 31 40
18.0 00 00 00 00 00 00 32 40
19.0 00 00 00 00 00 00 33 40
20.0 00 00 00 00 00 00 34 40
21.0 00 00 00 00 00 00 35 40
22.0 00 00 00 00 00 00 36 40
23.0 00 00 00 00 00 00 37 40
24.0 00 00 00 00 00 00 38 40
25.0 00 00 00 00 00 00 39 40
26.0 00 00 00 00 00 00 3a 40
27.0 00 00 00 00 00 00 3b 40
28.0 00 00 00 00 00 00 3c 40
29.0 00 00 00 00 00 00 3d 40
30.0 00 00 00 00 00 00 3e 40
31.0 00 00 00 00 00 00 3f 40
32.0 00 00 00 00 00 00 40 40
33.0 00 00 00 00 00 80 40 40
34.0 00 00 00 00 00 00 41 40
....


Feb 28 '06 #25
Keith Thompson <ks***@mib.org> writes:
Micah Cowan <mi***@cowan.name> writes:
[...]
__FILE__ and __LINE__ are special "macro"-like identifiers that the
preprocessor automatically replaces with the name of the file and the
line number (respectively) in which they appeared. These have been
around forever(?).


They're not just '"macro"-like identifiers'. They're macros.


Quite, sorry. I was too lazy to check that up.
Feb 28 '06 #26
On 2006-02-28, Micah Cowan <mi***@cowan.name> wrote:
Keith Thompson <ks***@mib.org> writes:
Micah Cowan <mi***@cowan.name> writes:
[...]
> __FILE__ and __LINE__ are special "macro"-like identifiers that the
> preprocessor automatically replaces with the name of the file and the
> line number (respectively) in which they appeared. These have been
> around forever(?).


They're not just '"macro"-like identifiers'. They're macros.


Quite, sorry. I was too lazy to check that up.


it's __function__ that has magic associated with it - its use causes a
local variable to have been declared in the top of the current function
scope.
Feb 28 '06 #27
Jordan Abel <ra*******@gmail.com> writes:
On 2006-02-28, Micah Cowan <mi***@cowan.name> wrote:
Keith Thompson <ks***@mib.org> writes:
Micah Cowan <mi***@cowan.name> writes:
[...]
> __FILE__ and __LINE__ are special "macro"-like identifiers that the
> preprocessor automatically replaces with the name of the file and the
> line number (respectively) in which they appeared. These have been
> around forever(?).

They're not just '"macro"-like identifiers'. They're macros.


Quite, sorry. I was too lazy to check that up.


it's __function__ that has magic associated with it - its use causes a
local variable to have been declared in the top of the current function
scope.


Actually, it's __func__. <OT>gcc has __FUNCTION__.</OT>

--
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.
Feb 28 '06 #28
Robin Haigh wrote:
.... snip ...
This code dumps out the internal representations of some 8-byte doubles:

#include <stdio.h>
char hex[] = "0123456789abcdef";
int main (void) {
int i;
double a;
unsigned char *pc;
pc = (unsigned char *)&a;
for ( i = 0 ; i < 50 ; i++ ) {
a = (double)i;
printf("%5.1f %c%c %c%c %c%c %c%c %c%c %c%c %c%c %c%c\n", a,
hex[pc[0] >> 4], hex[pc[0] & 0xf],
hex[pc[1] >> 4], hex[pc[1] & 0xf],
hex[pc[2] >> 4], hex[pc[2] & 0xf],
hex[pc[3] >> 4], hex[pc[3] & 0xf],
hex[pc[4] >> 4], hex[pc[4] & 0xf],
hex[pc[5] >> 4], hex[pc[5] & 0xf],
hex[pc[6] >> 4], hex[pc[6] & 0xf],
hex[pc[7] >> 4], hex[pc[7] & 0xf]);
}
return 0;
}

.... snip ...

on machines where a byte is 8 bits, and a double is 8 bytes. The
actual output may vary from what you got. You gotta know your
limitations.

On your machine it would probably make more sense to you if you
reversed the order of output bytes, i.e. dump pc[7] first, down
through pc[0].

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
Feb 28 '06 #29
Robin Haigh wrote:
"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:7f************@news.tdc.dk... -snip-
Hooray... My memory dump looks like this:

0x003A4DB8 00 00 00 00 00 00 f0 3f 00 00 00 00 00 00 00 40 00 00
......?.......@..
0x003A4DCA 00 00 00 00 08 40 00 00 00 00 00 00 10 40 00 00 00 00
.....@.......@....
0x003A4DDC 00 00 14 40 00 00 00 00 00 00 18 40 00 00 00 00 00 00
...@.......@......
...
...

That is double. As wrote earlier: I want see my numbers array 1 to 49? I
don't remember if a double value (double pointer?) takes 8 bytes but if
so, I remember that the first value (00 00 00 00 00 00 f0 3f) must be
something like: 3ff0 or something. Please tell me how to convert these
bytes from the memory dump to a memory location...

These are your doubles that you're looking at. Yes, they are 8 bytes, and
3ff0000000000000 is the internal representation of 1.0 as a double. You
don't have to do anything else to find it -- the trick would be to get it
displayed in a more human-readable display format


Do you or does anyone in here either know how to make MS visual studio
2005 do the trick or if there exists such a program I can download for
windows xp, so I can put up breakpoints and easily see if the right
values are in a particular location?

Might work well if I for instance just could copy/paste from the memory
dump to the conversion utility...
My guess is that I should look 0x003a4db8 and find out where it points
to (something with 3ff0 - please tell me, I'm not sure). And looking
*there* I hope to find the first array element: 1.0......?

No, 3a4db8 is the value of array[0], so it's the value of a double*, which
means it's the address of a double. So, when you're looking at the contents
of location 3a4db8, you're looking at the actual double, no more pointers to
follow.


Fine, ok.
nx and ny was not variables. They were #define'd if that makes any
difference...

It makes all the difference. It means your arrays are fixed size, not
variable, as far as the compiler is concerned. No mallocs required. Going
back to your original code,

void fillinnumbers(int fillvalue, int startx, int stopx, int starty, int
stopy, int array[][])
{
for(i=startx; i<=stopx; i++)
{
for(j=starty; j<=stopy; j++)
{
array[i][j] = fillvalue;
}
}
}

you can fix that just by changing int array[][] to int array[][ny+1]. That
doesn't work in any kind of C if ny is a variable, but if it's a macro for a
constant, no problem.


Ok, I'll test that later.
This code dumps out the internal representations of some 8-byte doubles:

#include <stdio.h>
char hex[] = "0123456789abcdef";
int main (void) {
int i;
double a;
unsigned char *pc;
pc = (unsigned char *)&a;
for ( i = 0 ; i < 50 ; i++ ) {
a = (double)i;
printf("%5.1f %c%c %c%c %c%c %c%c %c%c %c%c %c%c %c%c\n", a,
hex[pc[0] >> 4], hex[pc[0] & 0xf],
hex[pc[1] >> 4], hex[pc[1] & 0xf],
hex[pc[2] >> 4], hex[pc[2] & 0xf],
hex[pc[3] >> 4], hex[pc[3] & 0xf],
hex[pc[4] >> 4], hex[pc[4] & 0xf],
hex[pc[5] >> 4], hex[pc[5] & 0xf],
hex[pc[6] >> 4], hex[pc[6] & 0xf],
hex[pc[7] >> 4], hex[pc[7] & 0xf]);
}
return 0;
}

output:
0.0 00 00 00 00 00 00 00 00
1.0 00 00 00 00 00 00 f0 3f
2.0 00 00 00 00 00 00 00 40
3.0 00 00 00 00 00 00 08 40
4.0 00 00 00 00 00 00 10 40
5.0 00 00 00 00 00 00 14 40
6.0 00 00 00 00 00 00 18 40
7.0 00 00 00 00 00 00 1c 40
8.0 00 00 00 00 00 00 20 40
9.0 00 00 00 00 00 00 22 40
10.0 00 00 00 00 00 00 24 40

.....

Nice. Do you also have a code routine for going the other way?
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Feb 28 '06 #30
Robin Haigh wrote:
"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:7f************@news.tdc.dk... -snip-
These are your doubles that you're looking at. Yes, they are 8 bytes, and
3ff0000000000000 is the internal representation of 1.0 as a double. You
don't have to do anything else to find it -- the trick would be to get it
displayed in a more human-readable display format


Hmm... I tried this one:

http://babbage.cs.qc.edu/IEEE-754/IEEE-754.html

I don't think it works, does it? It either complaints about entering too
many or too few digits...
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Feb 28 '06 #31
Jordan Abel <ra*******@gmail.com> writes:
On 2006-02-28, Micah Cowan <mi***@cowan.name> wrote:
Keith Thompson <ks***@mib.org> writes:
Micah Cowan <mi***@cowan.name> writes:
[...]
> __FILE__ and __LINE__ are special "macro"-like identifiers that the
> preprocessor automatically replaces with the name of the file and the
> line number (respectively) in which they appeared. These have been
> around forever(?).

They're not just '"macro"-like identifiers'. They're macros.


Quite, sorry. I was too lazy to check that up.


it's __function__ that has magic associated with it - its use causes a
local variable to have been declared in the top of the current function
scope.


(As someone else reminded, it's __func__...)

Well, technically, AFA the standard is concerned, it's /always/
declared at the beginning of each function definition... it's just
that the "as-if" rule permits this obviously desirable optimization.
Feb 28 '06 #32
Keith Thompson wrote:
Micah Cowan <mi***@cowan.name> writes:
[...]
__FILE__ and __LINE__ are special "macro"-like identifiers that the
preprocessor automatically replaces with the name of the file and the
line number (respectively) in which they appeared. These have been
around forever(?).

They're not just '"macro"-like identifiers'. They're macros.


Okay... But I would still like an check-if-pointer-in-not-NULL-function
that returns an error if space could not be allocated...

Like:
int **array = malloc((nx+1)*sizeof(int*));
checkPtr_error(something here probably?)

int **var1 = malloc((nx+1)*sizeof(int*));
checkPtr_error(something here probably?)

int **var2 = malloc((nx+1)*sizeof(int*));
checkPtr_error(something here probably?)

int **doubleptr = malloc((nx+1)*sizeof(double*));
checkPtr_error(something here probably?)

etc.

So what would you suggest? Here's my old one (untested still):

checkPtr_error(%s location, %p pointer)
{
if (pointer == NULL)
{
fputs("Memory allocation failure (%s). Bye\n", location, stderr);
}
}
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Feb 28 '06 #33
Robin Haigh wrote:
"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:7f************@news.tdc.dk... -snip-
My guess is that I should look 0x003a4db8 and find out where it points
to (something with 3ff0 - please tell me, I'm not sure). And looking
*there* I hope to find the first array element: 1.0......?

No, 3a4db8 is the value of array[0], so it's the value of a double*, which
means it's the address of a double. So, when you're looking at the contents
of location 3a4db8, you're looking at the actual double, no more pointers to
follow.


Thanks! It seems to work now... I found out that if I right-clich I can
choose float 64 bits (or something) and then the debugger automatically
writes the values in double... Very nice.

Also, I found out I can just write 3a4db8 + 16*8 to move to index[16].
And the 16*8 is not even hexagonal - it's ordinary (10-base) decimal, so
it's really nice to use once I learned it :-)
nx and ny was not variables. They were #define'd if that makes any
difference...

It makes all the difference. It means your arrays are fixed size, not
variable, as far as the compiler is concerned. No mallocs required. Going
back to your original code,


I thought so...
void fillinnumbers(int fillvalue, int startx, int stopx, int starty, int
stopy, int array[][])
{
for(i=startx; i<=stopx; i++)
{
for(j=starty; j<=stopy; j++)
{
array[i][j] = fillvalue;
}
}
}

you can fix that just by changing int array[][] to int array[][ny+1]. That
doesn't work in any kind of C if ny is a variable, but if it's a macro for a
constant, no problem.

-snip-

Thanks again... I feel much "wiser" now :-)
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Feb 28 '06 #34
Martin Jørgensen schrieb:
Keith Thompson wrote:
Micah Cowan <mi***@cowan.name> writes:
[...]
__FILE__ and __LINE__ are special "macro"-like identifiers that the
preprocessor automatically replaces with the name of the file and the
line number (respectively) in which they appeared. These have been
around forever(?).
They're not just '"macro"-like identifiers'. They're macros.

Okay... But I would still like an check-if-pointer-in-not-NULL-function
that returns an error if space could not be allocated...

Like:
int **array = malloc((nx+1)*sizeof(int*));


Make that
int **array = malloc((nx + 1) * sizeof *array);
checkPtr_error(something here probably?)
<snip!>
int **doubleptr = malloc((nx+1)*sizeof(double*));
This here proves it nicely: if sizeof (double *) != sizeof (int *),
you may be in for a long bug hunt.
Once more
T **doubleptr = malloc((nx + 1) * sizeof *doubleptr);
is always correct irrespective of the actual type T represents.
checkPtr_error(something here probably?)

etc.

So what would you suggest? Here's my old one (untested still):

checkPtr_error(%s location, %p pointer)
{
if (pointer == NULL)
{
fputs("Memory allocation failure (%s). Bye\n", location, stderr);
}
}


*sigh* Please provide something that compiles.

You probably meant
void checkPtr_error(const char *location, const void *pointer)
{
if (pointer == NULL) {
fprintf(stderr, "Memory allocation failure (%s). Bye\n",
location ? location : "Unknown location");
exit(EXIT_FAILURE);
}
}

As pointed out elsethread:
- This does not take care of the already allocated memory,
open files and other resources.
- Generating a helpful, ideally unique location string to
facilitate debugging may be complex so that the generation
of the location string should ideally take place within
the if (pointer == NULL) case, i.e. outside of
checkPtr_error
- You do not gain anything substantial by using this function
instead of some kind of dedicated debug/error output function.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Feb 28 '06 #35
Martin Jørgensen <un*********@spam.jay.net> writes:
[...]
Okay... But I would still like an check-if-pointer-in-not-NULL-function
that returns an error if space could not be allocated... [snip] So what would you suggest? Here's my old one (untested still):

checkPtr_error(%s location, %p pointer)
{
if (pointer == NULL)
{
fputs("Memory allocation failure (%s). Bye\n", location, stderr);
}
}


No offense, but is that supposed to be C?

"%s" and "%p" are printf format specifiers, not something to be used
in a function declaration. fputs() doesn't take a format string; you
give it a "%s", which is just the characters '%' and 's' as far as
it's concerned. And if pointer is null, you print an error message,
but you continue executing with the bad value.

Perhaps you're looking for something like this:
================================
#include <stdio.h>
#include <stdlib.h>

void *checked_malloc(size_t size, char *file, int line)
{
void *result = malloc(size);
if (result == NULL) {
fprintf(stderr, "%s:%d malloc(%ld) failed\n", file, line, size);
exit(EXIT_FAILURE);
}
fprintf(stderr, "%s:%d malloc(%ld) ok\n", file, line, size);
return result;
}

#define CHECKED_MALLOC(size) checked_malloc(size, __FILE__, __LINE__);

int main(void)
{
void *ptr = CHECKED_MALLOC(100);
printf("ptr = %p\n", ptr);
return 0;
}
================================

The error handling is primitive; it simply aborts the program if
memory could not be allocated. Very likely there's not much more
you're going to be able to do, but in practice you might want to do
some cleanup; consider using atexit() to invoke any cleanup routines.
The "malloc ... ok" message shows you what the messages look like; you
won't want it in production 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.
Feb 28 '06 #36

"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:km************@news.tdc.dk...
Robin Haigh wrote:
"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:7f************@news.tdc.dk...

-snip-
These are your doubles that you're looking at. Yes, they are 8 bytes, and 3ff0000000000000 is the internal representation of 1.0 as a double. You
don't have to do anything else to find it -- the trick would be to get it displayed in a more human-readable display format


Hmm... I tried this one:

http://babbage.cs.qc.edu/IEEE-754/IEEE-754.html

I don't think it works, does it? It either complaints about entering too
many or too few digits...


works for me, yes. Takes 16 hex characters representing the 8 bytes in
big-endian byte order, so 3ff0000000000000 produces 1

--
RSH
Feb 28 '06 #37
Michael Mair wrote:
-snip-
int **doubleptr = malloc((nx+1)*sizeof(double*));

This here proves it nicely: if sizeof (double *) != sizeof (int *),
you may be in for a long bug hunt.


Ok.

-snip-
As pointed out elsethread:
- This does not take care of the already allocated memory,
open files and other resources.
My mallocs happens in the beginning of the program so no files or other
resources are opened at this point. The already allocated memory is
free'd when the program closes and if it can't get the memory it needs,
then it can't do anything about that at all and therefore I don't see
any problem with this method.
- Generating a helpful, ideally unique location string to
facilitate debugging may be complex so that the generation
of the location string should ideally take place within
the if (pointer == NULL) case, i.e. outside of
checkPtr_error
- You do not gain anything substantial by using this function
instead of some kind of dedicated debug/error output function.


I don't understand that viewpoint. I gain that substantial effect, that
I don't overwrite anything in memory because the program shuts itself
down before it tries to do anything stupid. Moreover, I get to know
exactly which malloc caused the error so I can see if I made any errors
at that point.
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 1 '06 #38
Keith Thompson wrote:
Martin Jørgensen <un*********@spam.jay.net> writes: -snip-
No offense, but is that supposed to be C?
No, that was some quick pseudo-/semi-C code. I didn't knew that was a
problem, because next time I could perhaps quickly just as well check it
through my compiler if that is a big problem. I just wanted to save some
time.
"%s" and "%p" are printf format specifiers, not something to be used
in a function declaration. fputs() doesn't take a format string; you
give it a "%s", which is just the characters '%' and 's' as far as
it's concerned. And if pointer is null, you print an error message,
but you continue executing with the bad value.
Well, I'm not a C-expert. Just began to learn it recently and I
know/knew that those are printf specifiers and not correctly used.
Perhaps you're looking for something like this:
================================
#include <stdio.h>
#include <stdlib.h>

void *checked_malloc(size_t size, char *file, int line)
{
void *result = malloc(size);
if (result == NULL) {
fprintf(stderr, "%s:%d malloc(%ld) failed\n", file, line, size);
exit(EXIT_FAILURE);
}
fprintf(stderr, "%s:%d malloc(%ld) ok\n", file, line, size);
return result;
}

#define CHECKED_MALLOC(size) checked_malloc(size, __FILE__, __LINE__);

int main(void)
{
void *ptr = CHECKED_MALLOC(100);
printf("ptr = %p\n", ptr);
return 0;
}
================================

The error handling is primitive; it simply aborts the program if
memory could not be allocated. Very likely there's not much more
That's fine enough for me. No data lost. In fact I like that code very
much...
you're going to be able to do, but in practice you might want to do
some cleanup; consider using atexit() to invoke any cleanup routines.
The "malloc ... ok" message shows you what the messages look like; you
won't want it in production code.


Got that... I also looked at atexit() from my C-book and there was a
nice example. I get the point. Thanks a lot for those comments... I
appreciate them.
Best regards / Med venlig hilsen
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Mar 1 '06 #39
Martin Jørgensen schrieb:
Michael Mair wrote:

[context: Using
void checkPtr_error(const char *location, const void *pointer)
{
if (pointer == NULL) {
fprintf(stderr, "Memory allocation failure (%s). Bye\n",
location ? location : "Unknown location");
exit(EXIT_FAILURE);
}
}
]
As pointed out elsethread:
- This does not take care of the already allocated memory,
open files and other resources.


My mallocs happens in the beginning of the program so no files or other
resources are opened at this point. The already allocated memory is
free'd when the program closes and if it can't get the memory it needs,
then it can't do anything about that at all and therefore I don't see
any problem with this method.


Do you handle the "already allocated memory" with atexit() to
be on the safe side? If you do: Yes, that takes care of it.
Otherwise, you are only _hoping_ that it is taken care of.

In your scenario (malloc() first) this may suffice.

However, you may find yourself calling the respective function
recursively or whatever -- if you then change your error
handling to returning an error in a less disruptive manner,
then you may still bind memory other processes might have
used. Or your programme becomes one or several library
functions and you can no longer die "just like that", then
returning an error but forgetting to free the memory may eat
up the storage slowly.

Apart from that: If you leave out calls to free() in the above
scenario, you may be tempted to leave them out in principle.
However, the programme-becomes-library thing applies much more
in this case; in addition, in my experience free()ing helps
find more errors than checking whether malloc() returned a
null pointer -- often writing over the boundaries of the
allocated storage makes itself felt when calling free().

As long as your operating system or implementation does not
_guarantee_ you that allocated storage is taken care of as if
you had free()d it explicitly, I'd rather explicitly free()
the storage.
- Generating a helpful, ideally unique location string to
facilitate debugging may be complex so that the generation
of the location string should ideally take place within
the if (pointer == NULL) case, i.e. outside of
checkPtr_error
- You do not gain anything substantial by using this function
instead of some kind of dedicated debug/error output function.


I don't understand that viewpoint. I gain that substantial effect, that
I don't overwrite anything in memory because the program shuts itself
down before it tries to do anything stupid. Moreover, I get to know
exactly which malloc caused the error so I can see if I made any errors
at that point.


If you malloc() all the memory essentially at once, the information
is not as valuable as you may think.
In this case you can as well go for
a = malloc(asize * sizeof *a);
...
foo = malloc(foosize * sizeof *foo);
if (!(a && ... && foo)) {
/* you can still find out the pointer where it first went wrong */
/* handle error */
}
without loosing anything. In fact, calling your checkPtr_error()
inside the fail branch for all returned pointers is perfectly
acceptable in my book as there is only a slight waste of time
in case of failure.

Keep the null pointer checks together with the malloc()s; see
Keith's CHECKED_MALLOC from <ln************@nuthaus.mib.org> which
does the same job as your suggestion with only one function/macro
call and keeps the checks together.

Cheers
Michael
PS: As a macro is used anyway, I'd consider going all the way:

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

/* belongs to some kind of "debug.c" */
#include <stdarg.h>

int DebugErrPrintf(const char *format, ...)
{
int ret;
va_list arglist;
va_start(arglist, format);
ret = vfprintf(stderr, format, arglist);
va_end(arglist);
return ret;
}

int DebugTracePrintf(const char *format, ...)
{
return 0;
}
/* end "debug.c" */

void *checked_malloc(size_t size,
const char *optInfo)
{
void *result = malloc(size);
if (result == NULL) {
DebugErrPrintf("%s malloc(%lu) failed\n",
optInfo ? optInfo : "", (unsigned long)size);
exit(EXIT_FAILURE);
}
DebugTracePrintf("%s malloc(%lu) ok\n",
optInfo ? optInfo : "", (unsigned long)size);
return result;
}

#define STRINGIZE(s) #s
#define XSTR(s) STRINGIZE(s)
#define CHECKED_BYTENO_MALLOC(dest, size) \
((dest) = checked_malloc((size), \
#dest ":" \
__FILE__ ":" \
XSTR(__LINE__) \
))
#define CHECKED_ARRAY_MALLOC(dest, size) \
CHECKED_BYTENO_MALLOC(dest, (size) * sizeof *(dest))

int main(void)
{
double *dptr;
void *vptr;

CHECKED_ARRAY_MALLOC(dptr, 42);
printf("dptr = %p\n", (void *)dptr);
free(dptr);

CHECKED_BYTENO_MALLOC(vptr, (size_t)-2);
printf("vptr = %p\n", vptr);
free(vptr);

return 0;
}

--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Mar 2 '06 #40
Michael Mair <Mi**********@invalid.invalid> writes:
[...]
As long as your operating system or implementation does not
_guarantee_ you that allocated storage is taken care of as if
you had free()d it explicitly, I'd rather explicitly free()
the storage.


Agreed, for several reasons (which you've already covered): the
program might some day become a function within a larger program, and
free() can sometimes show allocation errors that you would have
missed).

The common wisdom seems to be that memory allocated by malloc() will
*usually* be automatically deallocated by the operating system when
the program terminates (and will almost certainly be deallocated on
any modern OS), but that it's not guaranteed. I agree that it's not
guaranteed, but on the other hand, it's also not guaranteed that
calling free() will actually do any good.

More concretely:

#include <stdlib.h>
int main(void)
{
void *ptr = malloc(1000);
if (ptr == NULL) exit(EXIT_FAILURE);
#ifdef CALL_FREE
free(ptr);
#endif
exit(EXIT_SUCCESS);
}

On most systems, I'd expect the program to behave the same way whether
CALL_FREE is defined or not, i.e., the allocated memory will be
reclaimed when the program terminates. But if this program causes a
system-level memory leak without CALL_FREE, is there any reason to
assume defining CALL_FREE will plug the leak? Calling free() merely
causes the allocated space to be "made available for further
allocation", presumably within the program itself. It doesn't
necessarily return the space to the operating system *or* cause it to
be returned to the OS when the program terminates.

Are there any real-world systems where the above program actually
causes a memory leak with CALL_FREE not defined? If so, does defining
CALL_FREE actually plug the leak on all such systems?

None of this affects the principle that you should always free() all
the memory you malloc().

--
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.
Mar 2 '06 #41
Keith Thompson wrote:
Michael Mair <Mi**********@invalid.invalid> writes:
[...]
As long as your operating system or implementation does not
_guarantee_ you that allocated storage is taken care of as if
you had free()d it explicitly, I'd rather explicitly free()
the storage.


Agreed, for several reasons (which you've already covered): the
program might some day become a function within a larger program,
and free() can sometimes show allocation errors that you would
have missed).


There is one situation where you may want to avoid the 'free on
exit' action. This is where a large number of objects have been
allocated, and the free mechanism requires O(n) time to combine
free memory blocks (where n is the number of allocations in
effect). This can result in an O(n * n) action at program exit.

The test code for hashlib has provisions for enabling and disabling
this final action, and thus provides a way of measuring your
systems performance. This fault in free, which I found in all
libraries available to me, was the impetus behind my nmalloc system
for DJGPP. nmalloc makes all operation O(1), and obviates the
problem.

Your can find the relevant code (hashlib and nmalloc) at:

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

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
Mar 2 '06 #42
On Wed, 01 Mar 2006 20:57:32 -0500, CBFalconer <cb********@yahoo.com>
wrote:
Keith Thompson wrote:
Michael Mair <Mi**********@invalid.invalid> writes:
[...]
As long as your operating system or implementation does not
_guarantee_ you that allocated storage is taken care of as if
you had free()d it explicitly, I'd rather explicitly free()
the storage.
Agreed, for several reasons (which you've already covered): the
program might some day become a function within a larger program,
and free() can sometimes show allocation errors that you would
have missed).


There is one situation where you may want to avoid the 'free on
exit' action. This is where a large number of objects have been
allocated, and the free mechanism requires O(n) time to combine
free memory blocks (where n is the number of allocations in
effect). This can result in an O(n * n) action at program exit.

Another is where you have built a (complex) linked structure in
virtual memory significantly larger than available physical memory, so
that walking to free it requires swapping it (all) in, while OS-level
process cleanup can just discard the pages. This is usually O(n) or
slightly more, but with a large enough k to be troublesome.
The test code for hashlib has provisions for enabling and disabling
this final action, <snip>


I like that. It is almost always easier to include the free's while
originally coding and later remove or disable them, than to omit them
and later try to find or remember all the right places to add them.

- David.Thompson1 at worldnet.att.net
Mar 20 '06 #43

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

Similar topics

1
by: Carl Ogawa | last post by:
How do I make .cgi extention work? I installed ActivePerl 5.8. My CGI scripts work fine with .PL extention but not .CGI extention although I associated CGI extention as exactly same as PL...
7
by: Kapt. Boogschutter | last post by:
I'm trying to create a function that has at least 1 Argument but can also contain any number of Arguments (except 0 because my function would have no meaning for 0 argument). The arguments...
6
by: scottyman | last post by:
I can't make this script work properly. I've gone as far as I can with it and the rest is out of my ability. I can do some html editing but I'm lost in the Java world. The script at the bottom of...
7
by: The87Boy | last post by:
Is there any ways to make a function like system(), which returns more than one value (true or false) and (the array)
0
by: anupamak | last post by:
Hello, I am developing an application in VC++.Net and windows xp using the setupapi, which has to work as windows service. Actually, in the beginning, my application was developed in VC++.Net,...
3
by: zaeminkr | last post by:
I have class member data which is a pointer to class member function. However, I'm fail to compile the code. What is the correct grammar to make a function call by using static member data...
5
by: Peter Pei | last post by:
I am using things like "%-20s%-60s%-10s" in tkinter listbox to make it look like a table, with mono sized font like lucie system. But this does not work with data contains "Les misérables", because...
5
by: ravysters | last post by:
hi.. i have this procedure.. but its not working.. its showing some syntax errors.. how can i make this work.. please help create or replace function test(text) returns integer as $$...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
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: 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...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
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...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

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.