By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,194 Members | 817 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,194 IT Pros & Developers. It's quick & easy.

allocate and delete space question

P: n/a
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[i]=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);

Jul 23 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a
On 10 Apr 2005 17:42:34 -0700, "lixiaoyao" <li***********@yahoo.com>
wrote:
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;
}

--
Kanenas
Jul 23 '05 #2

P: n/a
hi kanenas
I am still wondering. your solutions is suggestive ,Is there someway
that I
do not need to rewrite the code?
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? 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;
}

--
Kanenas


Jul 23 '05 #3

P: n/a
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

Jul 23 '05 #4

P: n/a
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

Jul 23 '05 #5

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

On 14 Apr 2005 17:53:50 -0700, 18:12:12 -0700, 18:34:13 -0700,
"lixiaoyao" <li***********@yahoo.com> wrote:
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.
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.


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.
free()-ing a pointer to ndata will fail because ndata isn't
dynamically allocated.
For what this means, see above. If you don't know what static and
dynamic allocation are, read more about C memory management.
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?


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[i]='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
Jul 23 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.