I would like to create a new array of values, and I am not sure how to do this efficiently. Since to create the new array I have to call a function, passing the old array as a parameter. Right now my code looks something like:
float *newMeasurements1;
newMeasurements1 = malloc(sizeof(calcNewArray(oldArray)));
newMeasurements1 = calcNewArray(oldArray);
float *calcNewArray(float *oldArray) {
float *newArray;
int new_size = sizeof(oldArray) - outliers;
newArray = malloc((new_size) * sizeof(float));
for (i = 0; i < new_size; i++) {
newArray[i] = oldArray[i];
}
return newArray;
}
I am not sure if this is the correct way to do this because I have to call the function once to know the size of the new array. And then call the function a second time to actually assign the array to the allocated memory.
How best can I do this?
This line is useless:
newMeasurements1 = malloc(sizeof(calcNewArray(oldArray)));
just write this:
newMeasurements1 = calcNewArray(oldArray);
The malloc is already done in calcNewArray.
But there is another problem in calcNewArray, arrays decay to pointers to their first element when you pass them to a function, therefore sizeof(oldArray) is no the sizte bof the array you passed to calcNewArray but it is the size of a pointer. You need to pass the size of oldArray explicitely as a second parameter:
float *calcNewArray(float *oldArray, int oldsize) {
float *newArray;
int new_size = oldsize - outliers;
newArray = malloc((new_size) * sizeof(float));
for (i = 0; i < new_size; i++) {
newArray[i] = oldArray[i];
}
return newArray;
}
Related
I am using these lines to create variable size matrices:
Temp_Mat_0 = (double **)malloc((M)*sizeof(double ));
for (i=0;i<M;i++)
Temp_Mat_0[i] = (double *)malloc((N)*sizeof(double ));
They are working fine but I keep using them repeatedly in my code. I need to convert them to a function where I pass the pointer and the size. I was not able to do it due to pointers mess.
matrixAllocate(Matrix Pointer,rows,colms)
Can you help!
I think you'd be better off with a very simple scheme that allocates your matrix as a single contiguous block.
double **matrix_alloc(int rows, int cols)
{
/* Allocate array of row pointers */
double ** m = malloc(rows * sizeof(double*));
if (!m) return NULL;
/* Allocate block for data */
m[0] = malloc(rows * cols * sizeof(double));
if (!m[0]) {
free(m);
return NULL;
}
/* Assign row pointers */
for(int r = 1; r < rows; r++) {
m[r] = m[r-1]+cols;
}
return m;
}
This has the added bonus that when you free the matrix you don't need to remember how big it was:
matrix_free( double** m )
{
if (m) free(m[0]);
free(m);
}
As an extension to this, you might declare a struct that also keeps track of the number of rows and columns it has. e.g.
struct matrix {
int rows, cols;
double **m;
};
That makes your matrix functions look a little nicer (i.e. you can pass around struct matrix* instead of double**). It has the added bonus that the matrix dimension travels around with the associated data.
Using one contiguous block for your matrix data is generally preferable unless you have huge matrices. And it's very nice if your matrices are small, because you'll get the benefit of better memory locality in your CPU cache -- that means potential for faster code.
they are working fine
They do not seem really fine. Code should be changed to :
Temp_Mat_0 = malloc((M)*sizeof(double*)); //double* instead of double
if (Temp_Mat_0 == NULL)
return;
for (i = 0; i < M; i++){
Temp_Mat_0[i] = malloc((N)*sizeof(double));
if (Temp_Mat_0[i] == NULL){
free(Temp_Mat_0);
return;
}
}
Then, you can use a function like this :
double ** matrix_pointer = matrixAllocate(rows,colms);
where function matrixAllocate returns the pointer it allocated. For example :
matrixAllocate(rows,colms){
Temp_Mat_0 = malloc((rows)*sizeof(double*));
if (Temp_Mat_0 == NULL)
return NULL;
for (i = 0; i < rows; i++){
Temp_Mat_0[i] = malloc((colms)*sizeof(double));
if (Temp_Mat_0[i] == NULL){
free(Temp_Mat_0);
return NULL;
}
}
return Temp_Mat_0;
}
and call it like :
double **matrix pointer;
matrix pointer = matrixAllocate(rows, colms);
Don't forget to free the malloced memory afterwards.
for (i = 0; i < M; i++){
free(Temp_Mat_0[i]);
}
free(Temp_Mat_0);
Note that you should not cast the result of malloc, and you should also check if malloc was successful.
Whats wrong with this function, which is expected to add a row and a column to given 2D array? Matrix is symmetric.
void updateMatrix(double ***mat, int size, double *vec)
{ // mat is sizeXsize matrix, length of vec is size+1
*mat = (double**)realloc(*mat, (size + 1)*sizeof(double*));
(*mat)[size] = (double*)malloc((size + 1)*sizeof(double));
for(int i = 0; i < size + 1; i++) {
(*mat)[size][i] = vec[i];
}
for(int i = 0; i < size; i++) {
(*mat)[i] = (double*)realloc((*mat)[i], (size + 1)*sizeof(double));
(*mat)[i][size] = vec[i];
}
}
Your realloc is returning NULL in the second for loop..
I'm trying to figure out why.
Have you allocated everything before hand? Because chances are you might be passing a non NULL and non malloced pointer to realloc. And that is forbidden/will cause errors
Or, as says #MichaelDorgan , you could just be passing a gigantic size to your function but i sincereley hope you are not trying to allocate a few Go for an array. Otherwise i'm curious as to its use.
So i have read the other threads but i cant figure it out. My code is the following and it works fine.
double **sort(int counter, double **a){
int i, j;
double swap0, swap1;
for (i = 0 ; i < ( counter - 1 ); i++){
for (j = 0 ; j < counter - i - 1; j++){
if (a[0][j] > a[0][j+1]){
swap0 = a[0][j];
swap1 = a[1][j];
a[0][j] = a[0][j+1];
a[1][j] = a[1][j+1];
a[0][j+1] = swap0;
a[1][j+1] = swap1;
}
}
}
return a;
}
main(){
double **dist_table;
int i;
dist_table = (double **)calloc(2,sizeof(double*));
dist_table[0] = (double *)calloc(5,sizeof(double));
dist_table[1] = (double *)calloc(5,sizeof(double));
dist_table[0][0] = 5.1;
dist_table[1][0] = 0;
dist_table[0][1] = 6.1;
dist_table[1][1] = 1;
dist_table[0][2] = 3.1;
dist_table[1][2] = 2;
dist_table[0][3] = 2.1;
dist_table[1][3] = 3;
dist_table[0][4] = 7.1;
dist_table[1][4] = 4;
dist_table = sort(5, dist_table);
}
BUT i read that passing as an argument the **a is wrong. So why my codes runs fine, and which would be the right way?
Your function is just returning the same pointer you passed to it. Replacing:
dist_table = sort(5, distortable);
with:
sort(5, distortable);
would generally be better in this case, although sometimes returning the same value can be useful (e.g. if you want to use it within a larger expression).
For the last part of your question, passing a double ** would be wrong if you actually had a two-dimensional array of doubles, like this:
double my_array[2][5];
but that isn't what you have. You have a one-dimensional (dynamically allocated) array of double *, each element of which points to a one-dimensional (dynamically allocated) array of double. Actual multi-dimensional arrays are represented differently in memory to this, which is why passing a double ** would not work. But what you actually have here is completely different, and passing a double ** is fine, here.
Other unrelated points...
Casting the return from calloc() is completely unnecessary, and generally considered bad form. Better would be:
dist_table = calloc(2,sizeof(double*));
dist_table[0] = calloc(5,sizeof(double));
dist_table[1] = calloc(5,sizeof(double));
or better still:
dist_table = calloc(2,sizeof *dist_table);
for ( int i = 0; i < 2; ++i ) {
dist_table[i] = calloc(5,sizeof *(dist_table[i]));
}
Don't forget to check the return value of calloc() to find out if the allocation succeeded.
As long as you know the depth of the array and elements size you're doing it the right way.
Consider null terminating the array if the number of elements are dynamic and not limited to two.
Unable to find where the memory leak is happening in this code.
Basically I want to write a XS wrapper for a C-function which returns a two-dimensional array.
C-function:
int CW_returnArray(double** arrayDouble, int* count)
{
int number = 10;
int index, index1;
for(index = 0; index < number; index++)
{
for(index1 = 0; index1 < 10000; index1++)
{
arrayDouble[index][index1] = 12.51;
}
count[index] = 10000;
}
return number;
}
array -> output param to hold the two dimensional array
count -> output param to hold the number of element in each 1D array
XS wrapper:
void
returnArray()
PPCODE:
{
/** variable declaration **/
double** array;
int i = 0, j=0, status;
int* count;
int totalArrays;
SV** SVArrays; // to hold the references of 1D arrays
SV** SVtempArray; // temporary array to hold the elements of 1D array
/** allocate memory for C-type variables **/
New(0, array, 10, double*);
for(i = 0; i<10;i++)
{
New(0, array[i], 10000, double);
}
New(0, count, 10, int);
/** call C function **/
status = CW_returnArray(array, count);
/** check the status and retrieve the array to store it in stack **/
if(status > 0)
{
totalArrays = status;
New(0, SVArrays, totalArrays, SV*);
for(i = 0; i<totalArrays; i++)
{
/** allocate memory for temporary SV array **/
New(0, SVtempArray, count[i], SV*);
for(j = 0; j<count[i]; j++)
{
SVtempArray[j] = newSVnv(array[i][j]);
}
/** Make an array (AV) out of temporary SV array and store the reference in SVArrays **/
SVArrays[i] = newRV_noinc((SV*) av_make(count[i], SVtempArray));
/** free the memory allocated for temp SV array **/
for(j = 0; j<count[i]; j++)
{
sv_free(SVtempArray[j]);
}
Safefree(SVtempArray); SVtempArray = NULL;
}
}
else
{
totalArrays = 0;
}
/** push the return values to stack **/
EXTEND(SP, 2);
PUSHs(sv_2mortal(newSViv(status)));
PUSHs(sv_2mortal(newRV_noinc((SV*) av_make(totalArrays, SVArrays))));
/** clean up allocated memory for SV "array of array" , if needed **/
if(totalArrays > 0)
{
Safefree(SVArrays); SVArrays = NULL;
}
/** clean up allocated memory for C-type variables **/
for(i = 0; i<10;i++)
{
Safefree(array[i]);
}
Safefree(array); array = NULL;
Safefree(count); count = NULL;
}
An "array of array" is returned from XS.
testing in Perl script:
for(1..100)
{
my ($status, $arrayref) = returnArray();
undef $status;
$arrayref = [];
system('pause');
}
Every time the function returnArray() is called, the Commit size of Perl process is increasing.
But I would expect that the $arrayref variable should be garbage collected every time and the Memory usage should not increase.
I hope, I am freeing all the allocated memory in XS. But still there is a memory leak.
What is wrong with this XS code for memory leak?
Well, the pattern of "create a template array, do av_make(), then free the template" is not very good -- you'd be much better by simply creating your array with newAV(), av_extend()ing it to the right size, and then doing av_store(newSVnv(...)) for each element. That lets you avoid the intermediate SVtempArray allocations entirely.
However, that's not what you asked about. I think your problem is that you Safefree(SVArrays) without first sv_free()ing each element. Since av_make() duplicates the contents of the source array, AFAICT you're leaking the reference created by
SVArrays[i] = newRV_noinc((SV*) av_make(count[i], SVtempArray));
You'll need to iterate over SVArrays and call sv_free() on each element before you Safefree(SVArrays).
let's say I have a functions below.
void function createBands(boolean option) {
int i, j;
int ***bands = (int ***)malloc((SIZE + 1) * sizeof(int **));
for (i = 0; i < SIZE; i++) {
bands[i] = (int **)malloc(HEIGHT * sizeof(int *));
for (j = 0; j < HEIGHT; j++)
bands[i][j] = (int *)malloc(WIDTH * sizeof(int));
}
iterator *it =
createIterator(params); // do not be confused it is a structure with
// methods andaeribute just like Iterator class in
// java . Methods are poniters to functions.
repare_array(bands[Size], it);
}
void prepare_array(int **band, iterator *it) { read_array(band, it); }
read_array(int **band, iterator *it) {
for (int i = 0; i < Height; i++)
band[i] = (int *)it->next();
}
// Now in Iterator.c I have the iterator structure with the methods etc I will
// write just some line form iterator.
void *next() {
byte *b =
a function that reads bytes form a file and returns byte * CORECTLY !!!;
return b == NULL ? NULL : bytetoT(b);
// this function make void form byte conversion but it doesnt work so I make
// only a cast in read_aray as you see. SUppose just return b wich is byte(i
// know in C isn't any byte but I redeclared all the types to be JAVA.)
}
the questions is where I should allocate the bands because in this situation the 1D vector return by function is ok because I see the values in the function scope. But when it is return to array[i] I got a unallocated 3dVector.
I need to recieve bands[size][i][j] with the data form b. In b the data is good then I ve gote bands null.
What I have do so far I make another allocation in prepare aray before the call to read_array where I allocate **band and then I have some results but I am not confident.
Sorry for the confusion! And every comment is good for me. Maybe what I have do is ok I do not know!.
I am not new to C I just do not work with pointers for a long time.
If it is a 2D pointer(**) you have to assign it with the address of 2D array and if it is 1D array you have to assign it with the address of 1D array.
For your read_array function
read_array(int**array...)
{
for(i=0;i<HEIGHT(the same as in allocation);i++)
`enter code here`array[i] = function();//function return an 1D array
}
Make sure that function() returns the address of the 1D array.