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

Memory Corruption Problem

Hi,

Inspired by the recent post by "questions?" I started to write a simple
matrix library. My problem is that when I run the program below I get
unexpected results.

$ cat test.c
#include <stdio.h>
#include <stdlib.h>

#define SIZE 2

struct matrix
{
int rows, cols;
double **at;
};
typedef struct matrix Matrix;

Matrix *new_matrix(int rows, int cols, const double *elements)
{
Matrix *res;
int j, k;

res = malloc(sizeof (Matrix));
res->rows = rows;
res->cols = cols;
res->at = malloc(rows * sizeof (double *));
for (j = 0; j < rows; j++) {
res->at[j] = malloc(cols * sizeof (double *));
}
if (elements != NULL) {
for (j = 0; j < rows; j++) {
for (k = 0; k < cols; k++) {
res->at[j][k] = elements[j * cols + k];
}
}
}
return res;
}
int main(void)
{
Matrix *A, *B;
double a[SIZE * SIZE] = {1.0, 2.0, 3.0, 4.0};

A = new_matrix(SIZE, SIZE, a);
printf("%f\n", A->at[1][1]);
B = new_matrix(SIZE, SIZE, a);
printf("%f\n", A->at[1][1]);
return 0;
}
$ gcc -ansi -pedantic -std=c89 -Wall -g test.c module.c -o test
$ ./test
4.000000
0.000000

I expect the output to be

4.000000
4.000000

Any clues?
Regards,

August

--
I am the "ILOVEGNU" signature virus. Just copy me to your
signature. This email was infected under the terms of the GNU
General Public License.
Mar 1 '06 #1
19 1608
August Karlstrom wrote:
Hi,

Inspired by the recent post by "questions?" I started to write a simple
matrix library. My problem is that when I run the program below I get
unexpected results.

$ cat test.c
#include <stdio.h>
#include <stdlib.h>

#define SIZE 2

struct matrix
{
int rows, cols;
double **at;
};
typedef struct matrix Matrix; or all in one typedef struct matrix {...} Matrix;
Matrix *new_matrix(int rows, int cols, const double *elements)
{
Matrix *res;
int j, k;

res = malloc(sizeof (Matrix));
res->rows = rows;
res->cols = cols;
res->at = malloc(rows * sizeof (double *));
for (j = 0; j < rows; j++) {
res->at[j] = malloc(cols * sizeof (double *)); res->at[j] = malloc(cols * sizeof (double)); }
if (elements != NULL) {
for (j = 0; j < rows; j++) {
for (k = 0; k < cols; k++) {
res->at[j][k] = elements[j * cols + k]; sure ? it seems to be incoherent...
res->at[j][k] = elements[j * rows + k]; }
}
}
return res;
}
int main(void)
{
Matrix *A, *B;
double a[SIZE * SIZE] = {1.0, 2.0, 3.0, 4.0};

A = new_matrix(SIZE, SIZE, a);
printf("%f\n", A->at[1][1]);
B = new_matrix(SIZE, SIZE, a);
printf("%f\n", A->at[1][1]);
return 0;
}
$ gcc -ansi -pedantic -std=c89 -Wall -g test.c module.c -o test
$ ./test
4.000000
0.000000

I expect the output to be

4.000000
4.000000

Any clues?
Regards,

August


Xavier
Mar 1 '06 #2
Xavier wrote:
August Karlstrom wrote:
Hi,

Inspired by the recent post by "questions?" I started to write a
simple matrix library. My problem is that when I run the program below
I get unexpected results.

$ cat test.c
#include <stdio.h>
#include <stdlib.h>

#define SIZE 2

struct matrix
{
int rows, cols;
double **at;
};
typedef struct matrix Matrix;
or all in one typedef struct matrix {...} Matrix;

Matrix *new_matrix(int rows, int cols, const double *elements)
{
Matrix *res;
int j, k;

res = malloc(sizeof (Matrix));
res->rows = rows;
res->cols = cols;
res->at = malloc(rows * sizeof (double *));
for (j = 0; j < rows; j++) {
res->at[j] = malloc(cols * sizeof (double *));


res->at[j] = malloc(cols * sizeof (double));
}
if (elements != NULL) {
for (j = 0; j < rows; j++) {
for (k = 0; k < cols; k++) {
res->at[j][k] = elements[j * cols + k];


sure ? it seems to be incoherent...
res->at[j][k] = elements[j * rows + k];

you should put *values* in your array, isn't it?
*(res->at[j]+k) = *(elements+j * rows + k);
}
}
}
return res;
}
int main(void)
{
Matrix *A, *B;
double a[SIZE * SIZE] = {1.0, 2.0, 3.0, 4.0};

A = new_matrix(SIZE, SIZE, a);
printf("%f\n", A->at[1][1]);
B = new_matrix(SIZE, SIZE, a);
printf("%f\n", A->at[1][1]);
return 0;
}
$ gcc -ansi -pedantic -std=c89 -Wall -g test.c module.c -o test
$ ./test
4.000000
0.000000

I expect the output to be

4.000000
4.000000

Any clues?
Regards,

August


Xavier

Mar 1 '06 #3
August Karlstrom wrote:
$ cat test.c [snip] res->at = malloc(rows * sizeof (double *));
res->at = malloc(rows * sizeof *(res-at));
for (j = 0; j < rows; j++) {
res->at[j] = malloc(cols * sizeof (double *));
res->at[j] = malloc(cols * sizeof *(res->at[j]));
} [snip]
Any clues?

After a couple errors like that I always do

POINTER = malloc(ELEMS * sizeof *POINTER);

I tried your code as you posted it and got the
4.000000
0.000000
output. With the corrections noted above the output was what you
expected.
You should also free the allocated memory before exiting.

<OT>
If not free'd by the program will the OS free it?
</OT>

--
If you're posting through Google read <http://cfaj.freeshell.org/google>
Mar 1 '06 #4
On 1 Mar 2006 02:17:02 GMT, Pedro Graca <he****@dodgeit.com> wrote in
comp.lang.c:

[snip]

You should also free the allocated memory before exiting.

<OT>
If not free'd by the program will the OS free it?
</OT>


Some operating systems do, some do not. Most modern ones do, there
were certainly some older ones that did not.

The C standard has no control over operating systems, even operating
systems on which one might wish to execute C programs. So it cannot
impose requirements on what an operating system does before or after a
C program executes.

An early language decision, eventually codified in the standard, was
that normal termination of a program (return from main() or a call to
exit()) will close all open files, which includes flushing any
buffered data to the OS.

Another very specific decision was that normal program termination
would not be required to free allocated memory, and so most
implementations do not.

There is nothing preventing an implementation from walking its memory
allocation tables and freeing any still allocated memory on normal
termination. This is assuming that the implementation has retained
sufficient bookkeeping information to do so.

But once an implementation yields control back to the platforms by
returning a termination status, neither the executable nor the C
standard controls what the system does.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Mar 1 '06 #5
Xavier wrote:
August Karlstrom wrote:

[snip]
struct matrix
{
int rows, cols;
double **at;
};
typedef struct matrix Matrix;


or all in one typedef struct matrix {...} Matrix;


or just `typedef struct {} Matrix;' ;-) A style issue.
Matrix *new_matrix(int rows, int cols, const double *elements)
{
Matrix *res;
int j, k;

res = malloc(sizeof (Matrix));
res->rows = rows;
res->cols = cols;
res->at = malloc(rows * sizeof (double *));
for (j = 0; j < rows; j++) {
res->at[j] = malloc(cols * sizeof (double *));


res->at[j] = malloc(cols * sizeof (double));


Yes, there was the bug. Thanks.
}
if (elements != NULL) {
for (j = 0; j < rows; j++) {
for (k = 0; k < cols; k++) {
res->at[j][k] = elements[j * cols + k];


sure ? it seems to be incoherent...
res->at[j][k] = elements[j * rows + k];


No, `elements' contain the matrix rows (this should of course be
documented). There are j * cols elements above the row with index j.
Then we add k to get to the column.
August

--
I am the "ILOVEGNU" signature virus. Just copy me to your
signature. This email was infected under the terms of the GNU
General Public License.
Mar 1 '06 #6
Pedro Graca wrote:
You should also free the allocated memory before exiting.

<OT>
If not free'd by the program will the OS free it? Well that depends on the OS! But yes, a typical OS will, otherwise
you'd have a big problem with memory leeks when programs exit abnormally. </OT>

--
Ian Collins.
Mar 1 '06 #7
Xavier wrote:
Xavier wrote:

[snip]
res->at[j][k] = elements[j * rows + k];


you should put *values* in your array, isn't it?
*(res->at[j]+k) = *(elements+j * rows + k);


Different syntax, same semantics. I find subscripts less obscure.
August

--
I am the "ILOVEGNU" signature virus. Just copy me to your
signature. This email was infected under the terms of the GNU
General Public License.
Mar 1 '06 #8
August Karlstrom <fu********@comhem.se> writes:
Xavier wrote:
August Karlstrom wrote: [snip]
struct matrix
{
int rows, cols;
double **at;
};
typedef struct matrix Matrix;

or all in one typedef struct matrix {...} Matrix;


or just `typedef struct {} Matrix;'


Or just "struct matrix { ... };" and don't bother with the typedef.
;-) A style issue.


Indeed.

--
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 1 '06 #9
Pedro Graca wrote:
res->at = malloc(rows * sizeof *(res-at));

Oops :( ^^^^^^

I meant this instead
res->at = malloc(rows * sizeof *(res->at));

--
If you're posting through Google read <http://cfaj.freeshell.org/google>
Mar 1 '06 #10
Pedro Graca wrote:
August Karlstrom wrote: [snip]
res->at[j] = malloc(cols * sizeof (double *));

res->at[j] = malloc(cols * sizeof *(res->at[j]));


Thanks.
After a couple errors like that I always do

POINTER = malloc(ELEMS * sizeof *POINTER);
Yes, this is good practice unless POINTER is a very long expression. It
would be excellent if there was a LINT tool (static type checker) that
could detect errors like the one I made. At least SPLINT won't.
You should also free the allocated memory before exiting.

<OT>
If not free'd by the program will the OS free it?
</OT>


I rely on that. I think all modern OS:s do.
August

--
I am the "ILOVEGNU" signature virus. Just copy me to your
signature. This email was infected under the terms of the GNU
General Public License.
Mar 1 '06 #11
Keith Thompson wrote:
August Karlstrom <fu********@comhem.se> writes:
Xavier wrote:
August Karlstrom wrote:


[snip]
struct matrix
{
int rows, cols;
double **at;
};
typedef struct matrix Matrix;

or all in one typedef struct matrix {...} Matrix;


or just `typedef struct {} Matrix;'

Or just "struct matrix { ... };" and don't bother with the typedef.


IMHO this leads to overly verbose variable/parameter/field declarations.
August

--
I am the "ILOVEGNU" signature virus. Just copy me to your
signature. This email was infected under the terms of the GNU
General Public License.
Mar 1 '06 #12
Pedro Graca wrote:
After a couple errors like that I always do

POINTER = malloc(ELEMS * sizeof *POINTER);


So the C standard says it's OK to dereference an uninitialized pointer
in `sizeof' expressions, right?
August

--
I am the "ILOVEGNU" signature virus. Just copy me to your
signature. This email was infected under the terms of the GNU
General Public License.
Mar 1 '06 #13
August Karlstrom <fu********@comhem.se> writes:
Pedro Graca wrote:
After a couple errors like that I always do
POINTER = malloc(ELEMS * sizeof *POINTER);


So the C standard says it's OK to dereference an uninitialized pointer
in `sizeof' expressions, right?


Yes. The C standard says that the operand of sizeof is not evaluated
unless it's of variable length array type.

--
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 1 '06 #14
August Karlstrom wrote:
[...]
Matrix *new_matrix(int rows, int cols, const double *elements) {
Matrix *res;
int j, k;

res = malloc(sizeof (Matrix));
res->rows = rows;
res->cols = cols;
res->at = malloc(rows * sizeof (double *));
for (j = 0; j < rows; j++) {
res->at[j] = malloc(cols * sizeof (double *));


You've got a units error here. It should be:

res->at[j] = (double *) malloc (cols * sizeof (double));

The way to think about this is that the lowest level always is an array
of the base primitive. Another way is to realize that the units for
your first malloc is the same as the malloc for this one -- so
something must be wrong, since they are allocating different things.
You can make a macro like this:

#define arrAlloc(type,qty) (type *) malloc ((qty) * sizeof (type))

This will give you some semblance of type safety, as well as automatic
units checking:

res->at[j] = arrAlloc (double, cols);

And for the earlier allocation:

res->at = arrAlloc (double *, 1);

So you are not going to both a type mistmatch error, and a units error.
If you are worried about missing #include <stdlib.h> error, use a C++
compiler.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/

Mar 1 '06 #15
we******@gmail.com wrote:
August Karlstrom wrote:
[...]
Matrix *new_matrix(int rows, int cols, const double *elements) {
Matrix *res;
int j, k;

res = malloc(sizeof (Matrix));
res->rows = rows;
res->cols = cols;
res->at = malloc(rows * sizeof (double *));
for (j = 0; j < rows; j++) {
res->at[j] = malloc(cols * sizeof (double *));
You've got a units error here. It should be:

res->at[j] = (double *) malloc (cols * sizeof (double));


No. Never cast what `malloc` returns, it may hide errors (like not
including stdlib.h).

It should be:

res->at[j] = malloc (res->cols * sizeof ( *(res->at[j]) ) );

This has added benefit of guarding you from change in the type (think
complex numbers).

<snip>
So you are not going to both a type mistmatch error, and a units error.
If you are worried about missing #include <stdlib.h> error, use a C++
compiler.


Really, now!

--
BR, Vladimir

Mar 1 '06 #16
hi

Mar 1 '06 #17

mybirth1...@gmail.com wrote:
hi


lo

Mar 1 '06 #18
we******@gmail.com wrote:
August Karlstrom wrote:
[...]
Matrix *new_matrix(int rows, int cols, const double *elements) {
Matrix *res;
int j, k;

res = malloc(sizeof (Matrix));
res->rows = rows;
res->cols = cols;
res->at = malloc(rows * sizeof (double *));
for (j = 0; j < rows; j++) {
res->at[j] = malloc(cols * sizeof (double *));

You've got a units error here. It should be:

res->at[j] = (double *) malloc (cols * sizeof (double));

The way to think about this is that the lowest level always is an array
of the base primitive. Another way is to realize that the units for
your first malloc is the same as the malloc for this one -- so
something must be wrong, since they are allocating different things.
You can make a macro like this:

#define arrAlloc(type,qty) (type *) malloc ((qty) * sizeof (type))

This will give you some semblance of type safety, as well as automatic
units checking:

res->at[j] = arrAlloc (double, cols);

And for the earlier allocation:

res->at = arrAlloc (double *, 1);

So you are not going to both a type mistmatch error, and a units error.
If you are worried about missing #include <stdlib.h> error, use a C++
compiler.


Thanks for finding the bug and for the other hints.
August

--
I am the "ILOVEGNU" signature virus. Just copy me to your
signature. This email was infected under the terms of the GNU
General Public License.
Mar 1 '06 #19
On Wed, 01 Mar 2006 03:42:28 GMT, August Karlstrom
<fu********@comhem.se> wrote:
Pedro Graca wrote:
After a couple errors like that I always do

POINTER = malloc(ELEMS * sizeof *POINTER);


So the C standard says it's OK to dereference an uninitialized pointer
in `sizeof' expressions, right?


In this case, sizeof does not evaluate its operand so the pointer is
not dereferenced. It is not OK to dereference an uninitialized
pointer but that is not happening here.
Remove del for email
Mar 12 '06 #20

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

Similar topics

2
by: Pete | last post by:
I've run into an interesting memory problem. I think I'm running out of heap space, but I'm not sure.... I'm creating two new arrays like such.... pImage = new UBYTE ; pImageTemp = new...
5
by: Noa Garnett | last post by:
I'm developing on C++, using visual studio 6.0 with service pack 5. I have a memory corruption while debugging. Some of the variables I'm using are suddenly set to zero while progressing along the...
10
by: eyh5 | last post by:
Hi, My C code (running on Soalris Unix) has some "segmentation fault" that I wish to use purify to do it. I poked around the web, and found some information about adding some lines in a Makefile...
8
by: ranjeet.gupta | last post by:
Dear All Is the Root Cause of the Memory corruption is the Memory leak, ?? suppose If in the code there is Memory leak, Do this may lead to the Memory Corruption while executing the program ? ...
6
by: depkefamily | last post by:
I have a large C++ program using multiple vendors DLLs which is giving me a major headache. Under release mode I get exceptions thrown from what looks like a dereferenced corrupt pointer. The...
4
by: Harsha | last post by:
Hi All, There is some memory corruption in my application. It is due to the fact that it is multithreaded. Is this due to some missing mutex locking? Is there any way to find where it is...
4
by: T Clancey | last post by:
Hi, I have an app which connects to an Access database on a server, there are around 10 clients. It's a fairly heavy data intensive app, but most of the traffic is look up data. While the...
4
by: Tomassus | last post by:
Hi there, I have a problem with dynamic memory allocation. I know that it would have been easier to use vectors methods, but i want to know what i do here wrong. This is one of my methods in...
14
by: =?Utf-8?B?UHVjY2E=?= | last post by:
Hi, I'm using VS2005 and .net 2.0. I'm creating an application that has 3 forms. I want allow users to move forward and backward with the forms and retain the data users have entered. I thought...
66
by: Why Tea | last post by:
typedef struct some_struct { int i; short k, int m; char s; } some_struct_t; Assuming 16 bit or 32-bit alignment, can I assume that s always gets 4 or 8 bytes of allocation due to padding
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
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: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
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...

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.