allocate and delete space question

L

lixiaoyao

hi all
I use matrix & vector function to allocate the space myself in c,
typedef struct matrix_array newdata;
struct matrix_array{
float **sy,*sxx;
};
newdata ndata;//new data struct
ndata.sy=matrix(1,nvar,1,nstep);
ndata.sxx=vector(1,nstep);



the question lies there,if I free the space there,it will be ok,but if
I do like this way,


rkdumb(vstart,nvar,x1,x2,nstep,(void *)&ndata,derivefunc);
use void* to deference the data point, and free it after the
function,it will tell me
"Segmentation fault",who can tell me what is the reason?
thanks a lot






float **matrix(long nrl, long nrh, long ncl, long nch)
/* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch]
*/
{
long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
float **m;

/* allocate pointers to rows */
m=(float **) malloc((size_t)((nrow+NR_END)*sizeof(float*)));
if (!m) nrerror("allocation failure 1 in matrix()");
m += NR_END;
m -= nrl;

/* allocate rows and set pointers to them */
m[nrl]=(float *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(float)));
if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
m[nrl] += NR_END;
m[nrl] -= ncl;

for(i=nrl+1;i<=nrh;i++) m=m[i-1]+ncol;

/* return pointer to array of pointers to rows */
return m;
}

float *vector(long nl, long nh)
/* allocate a float vector with subscript range v[nl..nh] */
{
float *v;

v=(float *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(float)));
if (!v) nrerror("allocation failure in vector()");
return v-nl+NR_END;
}

ndata.sy=matrix(1,nvar,1,nstep);
 
K

Kanenas

hi all
I use matrix & vector function to allocate the space myself in c,

Below you'll find my guess as to what is going wrong, but you need to
take this question to comp.lang.c. One reason is the C++ approach is
quite different than the C implementation you give, and this newsgroup
is better suited for a C++ solution to the problem you are working on.

[...]
rkdumb(vstart,nvar,x1,x2,nstep,(void *)&ndata,derivefunc);
use void* to deference the data point, and free it after the
function,it will tell me
"Segmentation fault",who can tell me what is the reason?
thanks a lot
What does rkdumb free? "free(&ndata)"? "free(ndata.sy)"? Something
else? free()-ing a pointer to ndata will fail because ndata isn't
dynamically allocated. free()-ing ndata.sxx or ndata.sy will fail
because they point not to dynamically allocated memory but to some
point before the memory block (keep reading for details).
float **matrix(long nrl, long nrh, long ncl, long nch)
/* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch]
*/
{
long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
float **m;

/* allocate pointers to rows */
m=(float **) malloc((size_t)((nrow+NR_END)*sizeof(float*)));
if (!m) nrerror("allocation failure 1 in matrix()");
m += NR_END;
m -= nrl;
Altering m (and m[nrl]) means free(m) (and free(m[nrl])) will fail.
free(m+nrl-NR_END) (and free(m[nrl]+ncl-NR_END)) should work. If you
must use non-0 based indexing, I recommend using functions to perform
the indexing rather than altering m, as it's too easy to corrupt the
allocation information for the allocated memory block. For instance,
if the size of an allocated block is stored at *(malloc(size)-1), then
m[nrl-NR_END-1][ncl-NR_END-1]=0 would make it impossible to free the
block of memory.

Example indexing functions:

typedef struct matrix {
long nrl, ncl, nrow, ncol;
float **data;
} matrix_t;

//access functions
float* matrix_row(matrix_t matr, long row_idx)
{
row_idx-=nrl;
if (row_idx < matr.nrow) {
return matr.data[row_idx];
}
return NULL;
}
float matrix_element(matrix_t matr, long row_idx, long col_idx)
{
float* row= matrix_row(matr, row_idx);
if (row) {
col_idx -= matr.ncl;
if (col_idx < matr.ncol) {
return row[col_idx];
}
}
return FLT_NAN;
}

//assignment functions
float* set_matrix_row(matrix_t matr, long row_idx, float* row)
{
row_idx-=nrl;
if (row_idx < matr.nrow) {
memcpy(matr.data[row_idx], row, matr.ncol);
return matr.data[row_idx];
} else
return NULL;
}
float set_matrix_element(matrix_t matr,
long row_idx, long col_idx, float val)
{
float* row= matrix_row(matr, rowIdx);
if (row) {
col_idx -= matr.ncl;
if (col_idx < matr.ncol) {
row[col_idx]=val;
return val;
}
}
return FLT_NAN;
}
 
L

lixiaoyao

hi kanenas
I am still wondering. your solutions is suggestive ,Is there someway
that I
do not need to rewrite the code?
What does rkdumb free? "free(&ndata)"? "free(ndata.sy)"? Something
else? In there,It should free(&ndata),but I do not think it will
change
ndata.
free()-ing a pointer to ndata will fail because ndata isn't
dynamically allocated. free()-ing ndata.sxx or ndata.sy will fail
because they point not to dynamically allocated memory but to some
point before the memory block (keep reading for details). what does this mean?
float **matrix(long nrl, long nrh, long ncl, long nch)
/* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch]
*/
{
long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
float **m;

/* allocate pointers to rows */
m=(float **) malloc((size_t)((nrow+NR_END)*sizeof(float*)));
if (!m) nrerror("allocation failure 1 in matrix()");
m += NR_END;
m -= nrl;
Altering m (and m[nrl]) means free(m) (and free(m[nrl])) will fail.
free(m+nrl-NR_END) (and free(m[nrl]+ncl-NR_END)) should work. If you
must use non-0 based indexing, I recommend using functions to perform
the indexing rather than altering m, as it's too easy to corrupt the
allocation information for the allocated memory block. For instance,
if the size of an allocated block is stored at *(malloc(size)-1), then
m[nrl-NR_END-1][ncl-NR_END-1]=0 would make it impossible to free the
block of memory.

Example indexing functions:

typedef struct matrix {
long nrl, ncl, nrow, ncol;
float **data;
} matrix_t;

//access functions
float* matrix_row(matrix_t matr, long row_idx)
{
row_idx-=nrl;
if (row_idx < matr.nrow) {
return matr.data[row_idx];
}
return NULL;
}
float matrix_element(matrix_t matr, long row_idx, long col_idx)
{
float* row= matrix_row(matr, row_idx);
if (row) {
col_idx -= matr.ncl;
if (col_idx < matr.ncol) {
return row[col_idx];
}
}
return FLT_NAN;
}

//assignment functions
float* set_matrix_row(matrix_t matr, long row_idx, float* row)
{
row_idx-=nrl;
if (row_idx < matr.nrow) {
memcpy(matr.data[row_idx], row, matr.ncol);
return matr.data[row_idx];
} else
return NULL;
}
float set_matrix_element(matrix_t matr,
long row_idx, long col_idx, float val)
{
float* row= matrix_row(matr, rowIdx);
if (row) {
col_idx -= matr.ncl;
if (col_idx < matr.ncol) {
row[col_idx]=val;
return val;
}
}
return FLT_NAN;
}
 
L

lixiaoyao

float **matrix(long nrl, long nrh, long ncl, long nch)
/* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch]
*/
{
long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
float **m;

/* allocate pointers to rows */
m=(float **) malloc((size_t)((nrow+NR_END)*sizeof(float*)));
if (!m) nrerror("allocation failure 1 in matrix()");
m += NR_END;
m -= nrl;
Altering m (and m[nrl]) means free(m) (and free(m[nrl])) will fail.
free(m+nrl-NR_END) (and free(m[nrl]+ncl-NR_END)) should work. If you
must use non-0 based indexing, I recommend using functions to perform
the indexing rather than altering m, as it's too easy to corrupt the
allocation information for the allocated memory block. For instance,
if the size of an allocated block is stored at *(malloc(size)-1), then
m[nrl-NR_END-1][ncl-NR_END-1]=0 would make it impossible to free the
block of memory.

also,how does this expalin why it can be free before run the
rkdumb(vstart,nvar,x1,x2,nstep,(void *)&ndata,derivefunc);
thank you very much
BO
 
L

lixiaoyao

float **matrix(long nrl, long nrh, long ncl, long nch)
/* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch]
*/
{
long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
float **m;

/* allocate pointers to rows */
m=(float **) malloc((size_t)((nrow+NR_END)*sizeof(float*)));
if (!m) nrerror("allocation failure 1 in matrix()");
m += NR_END;
m -= nrl;
Altering m (and m[nrl]) means free(m) (and free(m[nrl])) will fail.
free(m+nrl-NR_END) (and free(m[nrl]+ncl-NR_END)) should work. If you
must use non-0 based indexing, I recommend using functions to perform
the indexing rather than altering m, as it's too easy to corrupt the
allocation information for the allocated memory block. For instance,
if the size of an allocated block is stored at *(malloc(size)-1), then
m[nrl-NR_END-1][ncl-NR_END-1]=0 would make it impossible to free the
block of memory.
also.I do not know why "if an allocated block is stored at
*(malloc(size)-1), then
m[nrl-NR_END-1][ncl-NR_END-1]=0 would make it impossible to free the
block of memory."
Thanks a lot
 
K

Kanenas

You really need to take this to comp.lang.c, as you may get more
informed answers regarding C memory management.

hi kanenas
I am still wondering. your solutions is suggestive ,Is there someway
that I
do not need to rewrite the code?

Yeah, define the segfault as a feature.

If you keep the current interface for indexing matrices, it will be
more error prone (as you've seen) than my suggested approach. Thus I
urge you to use functions to perform indexing.

From your subsequent questions, I'm guessing you don't quite grasp
memory management in C. Find a good explanation of it before you go
further with your project. Check out "The C Programming Language", by
Brian W. Kernighan and Dennis M. Ritchie. If you're not a native or
fluent English speaker, you can get a translated version. Section 7
of the C FAQ is devoted to memory management:
http://www.faqs.org/faqs/C-faq/faq/

You should be able to find many other webpages discussing C memory
management.
In there,It should free(&ndata),but I do not think it will
change ndata.

ndata isn't dynamically allocated, so don't free() a pointer to it.
You don't need to call free on a pointer unless it was obtained from
malloc, calloc or the like. Moreover, free()-ing a pointer to a
statically defined structure will corrupt the memory manager.

For what this means, see above. If you don't know what static and
dynamic allocation are, read more about C memory management.
what does this mean?

Did you keep reading? If not, keep reading this message for details
(as well as answers to other questions).
float **matrix(long nrl, long nrh, long ncl, long nch)
/* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch]
*/
{
long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
float **m;

/* allocate pointers to rows */
m=(float **) malloc((size_t)((nrow+NR_END)*sizeof(float*)));
if (!m) nrerror("allocation failure 1 in matrix()");
m += NR_END;
m -= nrl;
Altering m (and m[nrl]) means free(m) (and free(m[nrl])) will fail.
free(m+nrl-NR_END) (and free(m[nrl]+ncl-NR_END)) should work. If you
must use non-0 based indexing, I recommend using functions to perform
the indexing rather than altering m, as it's too easy to corrupt the
allocation information for the allocated memory block. For instance,
if the size of an allocated block is stored at *(malloc(size)-1), then
m[nrl-NR_END-1][ncl-NR_END-1]=0 would make it impossible to free the
block of memory.
also,how does this expalin why it can be free before run the
rkdumb(vstart,nvar,x1,x2,nstep,(void *)&ndata,derivefunc);
thank you very much

rkdumb must accidentally overwrite some portion of memory the C memory
manager (consisting of malloc/calloc/free &c.) uses to manage the
block, just as in the example:
m[nrl-NR_END-1][ncl-NR_END-1]=0
also.I do not know why "if an allocated block is stored at
*(malloc(size)-1), then

The size of a block may be stored at a point just before the block,
which I expressed as '*(malloc(size)-1)'. Suppose the following is
compiled and executed on a big-endian computer where sizeof(int) == 4.

char* p=malloc(5);
for (int i=0; i < 5; ++i)
p='a' + i;

The region surrounding *p may look like
... | ? | 0 | 0 | 0 | 5 | 'a' | 'b' | 'c' | 'd' | 'e' | ...
^
\--p points here

where '|' surround each byte in memory. If the following is executed:

p -= 5;
p[4] = ' '; //stores 32 at p[4]

the region of memory will look like:
.... | ? | 0 | 0 | 0 | 32 | 'a' | 'b' | 'c' | 'd' | 'e' | ...
^
\--p points here

free(p+5) will try to free 32 bytes, rather than 5. That's a problem.
Even more of a problem would be 'p[1]=127', in which case free(p+5)
would try to free a huge block (0x7F000000 + p[4] bytes) of memory and
probably end up producing a segfault.

Note this example assumes a particular layout for dynamically
allocated blocks. The size of a block may not be stored before a
block, but other data needed by free() may be stored there. By
altering the pointer, you make it easy to overwrite this data.

So here's what you need to do:
1) Read up on C memory management.
2) Go back over you code, making safe use of malloc, free and
dynamiclally allocated memory.
3) If you still have problems, post on comp.lang.c

Kanenas
 

Ask a Question

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

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

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,224
Latest member
BettieToom

Latest Threads

Top