GIDForums  

Go Back   GIDForums > Computer Programming Forums > C Programming Language
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 24-Feb-2005, 02:40
wu_weidong wu_weidong is offline
New Member
 
Join Date: Feb 2005
Posts: 14
wu_weidong is on a distinguished road

Dynamic Memory Allocation - Offset Pointers


Hi all,
I am just learning DMA, and am supposed to write 2 functions utilizing the offset technique, such that a 2-D array starts and ends the index of each dimension as the user specifies.

matrix(): creates a 2D array of float type numbers, indexing from -n to n for each dimension. A proper pointer is to be returned so that after invocation of this function, a 2D array of float type numbers and the specified starting and ending indices can be used.
free_matrix(): releases the memory allocated for the 2D array created by matrix().

I am using C, and use a UNIX-based compiler to run my program. Below is what I have:

CPP / C++ / C Code:
#include <stdio.h>
#include <stdlib.h>
float** matrix(float **x, int n);
void free_matrix(float **x, int n);
int main(void)
{
   float **x;
   int i, j, n;
   scanf("%d", &n);
   x = matrix(x, n);
   for (i = -n ; i <= n ; i++)
   {
       for (j = -n ; j <= n ; j++)
          x[i][j] = i + j;
   }
   for (i = -n ; i <= n ; i++)
   {
       for (j = -n ; j <= n ; j++)
       printf("%f ", x[i][j]);
       printf("\n");
   }
   free_matrix(x, n);
   return 0;
}
 
float** matrix(float **x, int n)
{
   int i;
   x = (float**) malloc(2 * n * sizeof(float*));
   for (i = 0 ; i < n ; i++)
   {
      x[i] = (float*) malloc(2 * n * sizeof(float));
      x[i] -= n;
   }
   x -= n;
   return x;
}

void free_matrix(float **x, int n)
{
   int i;
   x += n;
   for (i = 0 ; i < n ; i++)
      free(x[i] + n);
   free(x);
}


I keep getting the error "Segmentation fault". What is wrong with my code?

All code other than the functions were given in the question, so I can't change any of that. I followed the code to create the array closely with that given in my notes, which showed how to create a 2D array.

On a similar matter, I was able to create a 1D array (with starting and ending indices as -n and n respectively), but had problems freeing the memory. My function to free the memory was
CPP / C++ / C Code:
void free_vector(float *x, int n)
{
	free(x + n);
} 
but I got the same "Segmentation Fault" error. What is wrong?

Thank you.

Regards,
Rayne
Last edited by LuciWiz : 24-Feb-2005 at 03:13. Reason: Please insert your C code between [c] & [/c] tags
  #2  
Old 24-Feb-2005, 07:21
Dr. Evil Dr. Evil is offline
Member
 
Join Date: Oct 2004
Location: Netherlands
Posts: 120
Dr. Evil will become famous soon enough
I think one of your main problems was the fact that you kept adding or subtracting from x, thus moving the memory pointer, and then trying to access that memory. By doing that you'd be trying to get at memory that's not yours, so you'd probably get a runtime error about that. Another problem was the fact that on most of your loops you start with negative n, then incremented up to n, thus also trying to access memory that's not yours. Try something like this:

CPP / C++ / C Code:
#include <stdio.h>
#include <stdlib.h>
float** matrix(float **x, int n);
void free_matrix(float **x, int n);
int main(void)
{
   float **x;
   int i, j, n;
   scanf("%d", &n);
   x = matrix(x, n);
   for (i = 0 ; i < n ; i++)
   {
       for (j = 0 ; j < n ; j++)
          x[i][j] = i + j;
   }
   for (i = 0; i < n ; i++)
   {
       for (j = 0 ; j < n ; j++)
       printf("%f ", x[i][j]);
       printf("\n");
   }
   free_matrix(x, n);
   return 0;
}

float** matrix(float **x, int n)
{
   int i;
   x = (float**) malloc(n * sizeof(float));
   for (i = 0 ; i < n ; i++)
   {
      x[i] = (float*) malloc(n * sizeof(float));
      
   }
   
   return x;
}

void free_matrix(float **x, int n)
{
   int i;
   
   for (i = 0 ; i < n ; i++)
      free(x[i]);
   free(x);
}
  #3  
Old 24-Feb-2005, 08:33
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,703
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold
Quote:
Originally Posted by wu_weidong
Hi all,
I am just learning DMA, and am supposed to write 2 functions utilizing the offset technique, such that a 2-D array starts and ends the index of each dimension as the user specifies.

On a similar matter, I was able to create a 1D array (with starting and ending indices as -n and n respectively), but had problems freeing the memory. My function to free the memory was
CPP / C++ / C Code:
void free_vector(float *x, int n)
{
	free(x + n);
} 
but I got the same "Segmentation Fault" error. What is wrong?

Thank you.

Regards,
Rayne

If you can't do the 1D, why would you try the 2D? Get the 1D perfect, then expand.

You can to put printf statements after malloc() statements to see the range of memory.

You also need to analyze what the heck you need to do. I'll try to talk you through it the way that I would approach it.

First of all, say we want to allocate an array of chars so that we can refer to the chars as x[ i ] for i ranging from -2 to 2

How many elements are there:

The indices are -2, -1, 0, 1, 2.

Count them: five. In general, the number of integers ranging from -n to n is 2*n+1.

Now, let's suppose we get a memory block from malloc:

CPP / C++ / C Code:
char *x;

x = malloc((2*n+1)*sizeof(char));

Note that sizeof(char) is always 1, so you don't really need sizeof(char) in the expression, but if we get the program right for char, then later you just go through and substitute float or double or int or whetever, for char and the program will still work.

I always start something like this with char, since I print out memory addresses, and I don't have to worry about size of variables.

Now, for debug purposes, you can print out the value of the pointer you have just obtained from malloc, and you can print out addresses of everything in the memory block:

CPP / C++ / C Code:
char *allocate_pmvector(int n)
{
  char *retval;
  int i;

  retval = malloc((2*n+1) * sizeof(char)); 

  printf("malloc returned %p\n", retval);
  printf("This ****MUST**** be the value given to free()\n\n");
  if (retval) {
    printf("The range of addresses within the allocated region is:\n");
    for (i = 0; i < 2*n+1; i++) {
      printf("&retval[%d] = %p\n", i, retval+i);
    }
    /* Here's where you adjust the pointer so that you can
     * access the array from -n to n instead of 0 to 2*n-1
     */

    /*    ***You supply the code here ***   */

    printf("The range of addresses within the allocated region is:\n");
    for (i = -n; i <= n; i++) {
      printf("&retval[%d] = %p\n", i, retval+i);
    }
  }
  getchar(); /* Pause to look at the results before returing to main(). */
  return retval;
}

The idea is this: show every address within the block that you were given. If you were going to access the array with x[0] ... x[2*n-1], you would be through.

Now, adjust the pointer that you will return to the main program so that it can legally access from x[-n] up to and including x[n].

If the range of addresses from the second printout are not exactly the same as the first, ***stop***. Change the program to make it right. Then proceed.

An important note: Since you have changed the value of the address that malloc() gave you, you must change it back to the original address before calling free(). I repeat: free() must be given an address that you got from malloc().

If you have problems solving the 1D problem, post your code and ask specific questions.

Regards,

Dave
  #4  
Old 24-Feb-2005, 09:02
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,703
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold
Quote:
Originally Posted by Dr. Evil
I think one of your main problems was the fact that you kept adding or subtracting from x, thus moving the memory pointer, and then trying to access that memory. By doing that you'd be trying to get at memory that's not yours, so you'd probably get a runtime error about that. Another problem was the fact that on most of your loops you start with negative n, then incremented up to n, thus also trying to access memory that's not yours. Try something like this:

I think the whole point is that you can create arrays of any size, and by adjusting the pointer, you can access array elements with indices other than 0 to n-1.

It is critically important to realize that the C language doesn't do anything to prevent you from accessing memory outside of your allocated region. On the other hand you can access it lots of different ways

This expression:
CPP / C++ / C Code:
&x[ i ];

Is exactly equivalent to this

CPP / C++ / C Code:
x+i

(They are equivalent if and only if one of the variables, x or i, is a pointer to a data type (or an array name) and the other is an integer type variable)

This also means that this:

CPP / C++ / C Code:
x[i]

is exactly equivalent to this

CPP / C++ / C Code:
*(x + i)

In summary: If x is a pointer to some data type, this is not illegal code and will never give any compile-time error or warning message:

CPP / C++ / C Code:
  y = x[-2];

However if the address formed by pointer arithmetic x - 2 is outside the range of memory given to this program (by malloc or by any other legal means), the behavior is undefined. (That is, the code may generate a access violation error at run time --- or maybe not. The program may, in fact, appear to execute properly and give valid results today, but may crash tomorrow, or may run to completion but give incorrect answers, depending on what else is going on in your system).


Regards,

Dave
  #5  
Old 24-Feb-2005, 09:11
Dr. Evil Dr. Evil is offline
Member
 
Join Date: Oct 2004
Location: Netherlands
Posts: 120
Dr. Evil will become famous soon enough
Point taken about different ways of memory addressing, but I when I mentioned that that would cause a runtime error I was thinking along the lines of the os reaction and not any limitation to do with C.
  #6  
Old 24-Feb-2005, 09:22
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,703
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold
Quote:
Originally Posted by Dr. Evil
Point taken about different ways of memory addressing, but I when I mentioned that that would cause a runtime error I was thinking along the lines of the os reaction and not any limitation to do with C.

I totally agree with your statement that
Quote:
Originally Posted by Dr. Evil
you'd be trying to get at memory that's not yours, so you'd probably get a runtime error about that.

However I infer from the following that you are saying that using negative indices will necessarily access out-of-range memory.

Quote:
Originally Posted by Dr. Evil
Another problem was the fact that on most of your loops you start with negative n, then incremented up to n, thus also trying to access memory that's not yours.

The whole point was to create an array that can be accessed with indices from -n to n. This can be done by adjusting the pointer that malloc() gave you, as the original poster was attempting to do.

My point to him, was to start with the simpler case (1D array). Then, when he has nailed that, move on to 2D.

Regards,

Dave
  #7  
Old 24-Feb-2005, 09:48
wu_weidong wu_weidong is offline
New Member
 
Join Date: Feb 2005
Posts: 14
wu_weidong is on a distinguished road
Hi all, thanks for all your help. I realized that I overlooked the fact the array has 5 X 5 elements, and I needed to set the pointer in the "opposite" direction in order to get the indices -n to n. I managed to solve the problems, and once again, thanks for your help!

Regards,
Rayne
 
 

Recent GIDBlogMeeting the local Iraqis by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
2D arrays:dynamic allocation and freeing bravetanveer C Programming Language 48 27-Nov-2007 15:55
Why seg fault in char array? nusstu C Programming Language 11 24-Aug-2004 16:10
3D array dynamic memory allocation cjwatchdog C Programming Language 3 20-Feb-2004 15:27

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 05:11.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.