C-Passing an 3d array,allocation and population - c

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.

Related

Copy 2D array to new buffer with memcpy

I want to copy an 2D array to a new 2D array within an internal buffer.
Let's suppose I have the following function:
uint8 the_2D_array[100][7];
void Get_2D_Array(uint8 **array)
{
*array = &the_2D_array[0][0]; // Function which returns pointer to the first element of the 2D array
}
Later in my code I'm expecting to do something like this:
myBuffered_Aray[100][7];
uint8 *pValues;
Get_2D_Array(&pValues)
{
for (uint8 i = 0; i < 100; i++)
{
for (uint8 j = 0; j < 7; j++)
{
(void)memcpy(myBuffered_Aray[i][j], (u8_t*)&pValues[i][j], sizeof(uint8));
}
}
}
The part with
(u8_t*)&pValues[i][j]
will not work because of "Expression must have pointer to object type".
How to do it correctly?

Allocate and assign to memory efficiently

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;
}

Create vector char array of strings

I am trying to create an array of c string in C, which simulates a behavior similar to that of vector array in c++. The array doubles its capacity whenever the (currentSize + 1) is equal to (MAX_SIZE). This is how I am doing it:
void addLog(char ** dynamicArray, int* size, int *maxSize, int command){
if (*size < *maxSize){
dynamicArray[*size] = "User selects option 1 from main menu.";
(*size)++;
}
else{
//resizing the array here
int originalSize = *maxSize;
*maxSize = *maxSize * 2;
//copy elements of dynamic array in temporary array
char **tempArray = (char**)malloc(originalSize * sizeof(char*));
for (int i = 0; i < originalSize; ++i){
memcpy(&tempArray[i], &dynamicArray[i], sizeof(dynamicArray[i]));
}
//create new array of max * 2 size
dynamicArray = (char**)malloc(*maxSize * sizeof(char*));
//copy temp to dynamic
for (int i = 0; i < originalSize; ++i){
memcpy(&dynamicArray[i], &tempArray[i], strlen(tempArray[i]));
}
for (int i = 0; i < originalSize; i++) {
free(tempArray[i]); <---- this throws an exception on heap
}
free(tempArray);
//insert new element now
dynamicArray[*size] = "User selects option 1 from main menu.";
(*size)++;
}
}
I believe this is a trivial problem for a deep copy scenario. How to resize dynamic array to 2 * capacity and then free the temporary existing elements?
You could create a reusable implementation yourself by extending a struct.
This is a bit long, but it walks you through the entire process and should have everything you need to know:
http://eddmann.com/posts/implementing-a-dynamic-vector-array-in-c/
The structure will take advantage of a fixed-size array, with a counter invariant that keeps track of how many elements are currently present. If the underlying array becomes exhausted, the addition operation will re-allocate the contents to a larger size, by way of a copy."

function to modify 2d array to add row an a column using realloc

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.

XS Memory leak in this code?

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).

Resources