I need to fill sparse matrix with random elemnts. I am trying to get random elements and write them as value, column and row elements of their arrays but I keep running into segmentation faults.
This only happens if I set N=1000 then SIZE=10000 (because if I set SIZE=1000 or less, it works).
Does that mean I can't allocate all this memory or access it after I allocated it?
What should I do if I really need to get all this memory (SIZE=10'000) allocated? can someone please help me?
#include <stdio.h>
#include <stdlib.h>
typedef struct _matrix {
int size; //number of not-null elements
int ord; //order of matrix
int* val;
int* col;
int* row;
} matrix;
matrix init (int ord, int size)
{
matrix m;
m.ord = ord;
m.size = size;
m.val = malloc(sizeof(int) * size);
m.val = malloc(sizeof(int) * size);
m.val = malloc(sizeof(int) * size);
return m;
}
matrix fill_matrix (int ord)
{
int i, j, gap, size = ord * ord / 100;
matrix new_matrix = init(ord, size);
j = 1;
for (i = 0; i < size; i++) {
new_matrix.val[i] = rand() % 9 + 1;
new_matrix.col[i] = rand() % ord + 1; //<------SEGFAULT
new_matrix.row[i] = rand() % ord + 1;
j++;
}
return new_matrix;
}
int main()
{
matrix A;
int n = 1000;
A = fill_matrix(n);
return 0;
}
You assign to val three times, but never initialize the other two pointers.
m.val = malloc(sizeof(int) * size);
m.val = malloc(sizeof(int) * size);
m.val = malloc(sizeof(int) * size);
I'm guessing you meant this:
m.val = malloc(sizeof(int) * size);
m.col = malloc(sizeof(int) * size);
m.row = malloc(sizeof(int) * size);
m.val = malloc(sizeof(int) * size);
m.val = malloc(sizeof(int) * size);
m.val = malloc(sizeof(int) * size);
You never malloc m.col and m.row :-) Cut & Paste programming is evil...
Related
I know this has been discussed here plenty of times, but I simply cannot see what I'm doing wrong. Here's the snippet.
#include <stdio.h>
#include <stdlib.h>
double** SEG = NULL;
void main ()
{
int i;
int seg_counter = 0;
SEG = (double**) malloc(1 * sizeof(double *));
for(i=0; i < 1; i++)
{
*(SEG + i) = (double*) malloc(9 * sizeof(double));
}
while (1)
{
SEG = (double**) realloc(SEG, seg_counter+1 * sizeof(double *));
for(i=seg_counter; i < seg_counter+1; ++i)
{
*(SEG + i) = (double*) malloc(9 * sizeof(double));
}
printf ("%d\n", seg_counter);
seg_counter++;
}
}
The goal is to add one row each time the loop is executed. I'm getting a memory error instead.
Thnx for any help here!
You do not have a 2D array only an array of pointers. You can have real 2D if you use array pointers.
Do not use types only objects in the sizeof
void *addRow(size_t *rows, const size_t cols, double (*array)[cols])
{
array = realloc(array, (*rows + 1) * sizeof(*array));
if(array) *rows += 1;
return array;
}
int main(void)
{
size_t cols = 10, rows = 0;
double (*array)[cols] = NULL;
for(size_t i = 0; i < 10; i ++)
{
void *tmp;
tmp = addRow(&rows, cols, array);
if(tmp)
{
array = tmp;
printf("Added another row!!!!! Rows = %zu\n", rows);
}
}
free(array);
}
You can also add some checks.
void *addRow(size_t *rows, const size_t cols, double (*array)[*rows])
{
if(rows && cols)
{
array = realloc(array, (*rows + 1) * sizeof(*array));
if(array) *rows += 1;
}
return array;
}
For starters you should set the variable seg_counter to 1 after this memory allocation
int seg_counter = 0;
SEG = (double**) malloc(1 * sizeof(double *));
++seg_counter;
Or you could write
int seg_counter = 1;
SEG = (double**) malloc( seg_counter * sizeof(double *));
Then the following for loop (that is in fact redundant) will look like
for(i=0; i < seg_counter; i++)
{
*(SEG + i) = (double*) malloc(9 * sizeof(double));
}
This statement
SEG = (double**) realloc(SEG, seg_counter+1 * sizeof(double *));
has a typo, You need to write
SEG = (double**) realloc(SEG, ( seg_counter+1 ) * sizeof(double *));
Again the next for loop is redundant. You could just write
*(SEG + seg_counter) = (double*) malloc(9 * sizeof(double));
and then
seg_counter++;
printf ("%d\n", seg_counter);
As you have an infinite while loop then your program will be aborted when memory can not be allocated.
I made a structure (SomeMisc) which has a float array, so I can fill it with some values, and then try to memcpy its float array to a different struct's float array, and print out the result to see if it worked.
The other structure (ArrayPairs) is supposed to hold two arrays of arrays. So that low[i] belongs to high[i] and vice versa when I want to make some changes on "a couple".
So I make 2 SomeMisc objects, fill their arrays with numbers, and then try to make a function where I expand the low-array and high-array of the ArrayPairs object with realloc firstly, then I try to malloc space to the new rows, and then finally memcpy content from the 2 SomeMisc member arrays given as arguments to the function.
But it keeps resulting in segmentation faults and/or undefined behavior, and I can't figure out why.
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include <stdlib.h>
typedef struct some{
int32_t len;
float* arr;
} SomeMisc;
typedef struct arrPrs{
int32_t amountOfRows;
int32_t amountOfColumns;
float** low;
float** high;
} ArrayPairs;
void initializeArrayPairArray(ArrayPairs* AP, int32_t length, int32_t width){
AP->amountOfRows = length;
AP->amountOfColumns = width;
AP->low = (float**)malloc(length * sizeof(float*));
AP->high = (float**)malloc(length * sizeof(float*));
for(int i=0; i<length; i++){
AP->low[i] = (float*)malloc(width * sizeof(float));
AP->high[i] = (float*)malloc(width * sizeof(float));
for(int j=0; j<width; j++){
AP->low[i][j] = 32;
AP->high[i][j] = 44;
}
}
}
void addArrayPair(ArrayPairs* AP, float* low, float* high){
AP->amountOfRows++;
AP->low = (float**)realloc(AP->low, AP->amountOfRows * sizeof(float*));
AP->high = (float**)realloc(AP->high, AP->amountOfRows * sizeof(float*));
AP->low[AP->amountOfRows] = (float*)malloc(AP->amountOfColumns * sizeof(float));
AP->high[AP->amountOfRows] = (float*)malloc(AP->amountOfColumns * sizeof(float));
memcpy(AP->low[AP->amountOfRows], low, AP->amountOfColumns * sizeof(float));
memcpy(AP->high[AP->amountOfRows], high, AP->amountOfColumns * sizeof(float));
printf("TESTING PRINT: %.2f\n", AP->high[10][5]);
}
int main () {
int32_t nrOfCols = 8;
int32_t nrOfRows = 10;
ArrayPairs arr;
initializeArrayPairArray(&arr, nrOfRows, nrOfCols);
int32_t mArrLength = 2;
SomeMisc* mArr = (SomeMisc*)malloc(mArrLength*sizeof(SomeMisc));
for(int i=0; i<mArrLength; i++){
mArr[i].arr = (float*)malloc(nrOfCols*sizeof(float));
for(int j=0; j<nrOfCols; j++){
mArr[i].arr[j] = (i+1)*j;
}
}
addArrayPair(&arr, mArr[0].arr, mArr[1].arr);
printf("LOW:\tHIGH:\n");
for(int i=9; i<arr.amountOfRows; i++){
printf("INDEX: %d\n",i);
for(int j=0; j<arr.amountOfColumns; j++){
printf("%.2f\t%.2f\n",arr.low[i][j],arr.high[i][j]);
}
printf("\n");
}
return(0);
}
I followed this answer: 2d array realloc Segmentation Fault Error
But I already have the ArrayPairs* AP in the parameter list of addArrayPair, and the & with the object arr when calling the function.
I also tried dereferencing as was suggested in that answer, but this didn't work either:
void addArrayPair(ArrayPairs* AP, float* low, float* high){
(*AP).amountOfRows++;
(*AP).low = (float**)realloc((*AP).low, AP->amountOfRows * sizeof(float*));
(*AP).high = (float**)realloc((*AP).high, AP->amountOfRows * sizeof(float*));
(*AP).low[AP->amountOfRows] = (float*)malloc((*AP).amountOfColumns * sizeof(float));
(*AP).high[AP->amountOfRows] = (float*)malloc((*AP).amountOfColumns * sizeof(float));
memcpy((*AP).low[(*AP).amountOfRows], low, (*AP).amountOfColumns * sizeof(float));
memcpy((*AP).high[(*AP).amountOfRows], high, (*AP).amountOfColumns * sizeof(float));
}
You increase AP->amountOfRows too early. That means when you do AP->low[AP->amountOfRows] you will use an out-of-bounds index, and have undefined behavior
Instead (re)allocate AP->amountOfRows + 1 elements, and increase AP->amountOfRows once all allocations and copying is done:
void addArrayPair(ArrayPairs* AP, float* low, float* high){
AP->low = realloc(AP->low, (AP->amountOfRows + 1) * sizeof(float*));
AP->high = realloc(AP->high, (AP->amountOfRows + 1) * sizeof(float*));
AP->low[AP->amountOfRows] = malloc(AP->amountOfColumns * sizeof(float));
AP->high[AP->amountOfRows] = malloc(AP->amountOfColumns * sizeof(float));
memcpy(AP->low[AP->amountOfRows], low, AP->amountOfColumns * sizeof(float));
memcpy(AP->high[AP->amountOfRows], high, AP->amountOfColumns * sizeof(float));
// Increase once all is done
AP->amountOfRows++;
}
I'm using an example from https://phoxis.org/2012/07/12/get-sorted-index-orderting-of-an-array/ where he returns the sort indices from a sort of an array, i.e.
3,4,2,6,8 returns 4,3,1,0,2 (+1 for each index in R). This is the equivalent of R's order function
I've translated his/her code to work as a function returning an array of sorted indices. The code gives the correct answer.
keeping track of the original indices of an array after sorting in C has a similar response, but as #BLUEPIXY warns, his solution doesn't work in all circumstances. I need something that will work in all circumstances, including ties.
however, the original author uses a global pointer, which causes a memory leak, and free() doesn't fix it. which I don't know how to do this without the global pointer.
How can I fix this memory leak, or at least return sorted indices in C that will always work?
#include <stdio.h>
#include <stdlib.h>
/* holds the address of the array of which the sorted index
* order needs to be found
*/
int * base_arr = NULL;
/* Note how the compare function compares the values of the
* array to be sorted. The passed value to this function
* by `qsort' are actually the `idx' array elements.
*/
static int compar_increase (const void * a, const void * b) {
int aa = *((int * ) a), bb = *((int *) b);
if (base_arr[aa] < base_arr[bb]) {
return 1;
} else if (base_arr[aa] == base_arr[bb]) {
return 0;
} else {
// if (base_arr[aa] > base_arr[bb])
return -1;
}
}
int * order_int (const int * ARRAY, const size_t SIZE) {
int * idx = malloc(SIZE * sizeof(int));
base_arr = malloc(sizeof(int) * SIZE);
for (size_t i = 0; i < SIZE; i++) {
base_arr[i] = ARRAY[i];
idx[i] = i;
}
qsort(idx, SIZE, sizeof(int), compar_increase);
free(base_arr); base_arr = NULL;
return idx;
}
int main () {
const int a[] = {3,4,2,6,8};
int * b = malloc(sizeof(int) * sizeof(a) / sizeof (*a));
b = order_int(a, sizeof(a) / sizeof(*a));
for (size_t i = 0; i < sizeof(a)/sizeof(*a); i++) {
printf("b[%lu] = %d\n", i, b[i]+1);
}
free(b); b = NULL;
return 0;
}
A straightforward approach without using a global variable can look the following way
#include <stdio.h>
#include <stdlib.h>
int cmp_ptr(const void *a, const void *b)
{
const int **left = (const int **)a;
const int **right = (const int **)b;
return (**left < **right) - (**right < **left);
}
size_t * order_int(const int *a, size_t n)
{
const int **pointers = malloc(n * sizeof(const int *));
for (size_t i = 0; i < n; i++) pointers[i] = a + i;
qsort(pointers, n, sizeof(const int *), cmp_ptr);
size_t *indices = malloc(n * sizeof(size_t));
for (size_t i = 0; i < n; i++) indices[i] = pointers[i] - a;
free(pointers);
return indices;
}
int main( void )
{
const int a[] = { 3,4,2,6,8 };
const size_t N = sizeof(a) / sizeof(*a);
size_t *indices = order_int(a, N);
for (size_t i = 0; i < N; i++) printf("%d ", a[indices[i]]);
putchar('\n');
free(indices);
return 0;
}
The program output is
8 6 4 3 2
As for the memory leak then it is due to overwriting the value of the pointer to redundantly allocated memory.
int * b = malloc(sizeof(int) * sizeof(a) / sizeof (*a));
b = order_int(a, sizeof(a) / sizeof(*a));
The memory allocation does not make sense.
The problem I see is that within main function - you are allocating pointer b some memory -
int * b = malloc(sizeof(int) * sizeof(a) / sizeof (*a));
The next line calls order_int(...) that returns a pointer to already allocated memory -
b = order_int(a, sizeof(a) / sizeof(*a));
Looking at the order_int function -
int * order_int (const int * ARRAY, const size_t SIZE) {
int * idx = malloc(SIZE * sizeof(int));
base_arr = malloc(sizeof(int) * SIZE);
for (size_t i = 0; i < SIZE; i++) {
base_arr[i] = ARRAY[i];
idx[i] = i;
}
qsort(idx, SIZE, sizeof(int), compar_increase);
free(base_arr); base_arr = NULL;
return idx;
}
.. you see that idx has been already been allocated the correct memory.
I would suggest removing the malloc from b - see below.
int * b = NULL;
If I allocate a 2D array like this int a[N][N]; it will allocate a contiguous block of memory.
But if I try to do it dynamically like this :
int **a = malloc(rows * sizeof(int*));
for(int i = 0; i < rows; i++)
a[i] = malloc(cols * sizeof(int));
This maintains a unit stride between the elements in the rows, but this may not be the case between rows.
One solution is to convert from 2D to 1D, besides that, is there another way to do it?
If your array dimensions are known at compile time:
#define ROWS ...
#define COLS ...
int (*arr)[COLS] = malloc(sizeof *arr * ROWS);
if (arr)
{
// do stuff with arr[i][j]
free(arr);
}
If your array dimensions are not known at compile time, and you are using a C99 compiler or a C2011 compiler that supports variable length arrays:
size_t rows, cols;
// assign rows and cols
int (*arr)[cols] = malloc(sizeof *arr * rows);
if (arr)
{
// do stuff with arr[i][j]
free(arr);
}
If your array dimensions are not known at compile time, and you are not using a C99 compiler or a C2011 compiler that supports variable-length arrays:
size_t rows, cols;
// assign rows and cols
int *arr = malloc(sizeof *arr * rows * cols);
{
// do stuff with arr[i * rows + j]
free(arr);
}
In fact, n-dimensional arrays (allocated on the stack) are really just 1-dimension vectors. The multiple indexing is just syntactic sugar. But you can write an accessor function to emulate something like what you want:
int index_array(int *arr, size_t width, int x, int y)
{
return arr[x * width + y];
}
const size_t width = 3;
const size_t height = 2;
int *arr = malloc(width * height * sizeof(*arr));
// ... fill it with values, then access it:
int arr_1_1 = index_array(arr, width, 1, 1);
However, if you have C99 support, then declaring a pointer to an array is possible, and you can even use the syntactic sugar:
int (*arr)[width] = malloc(sizeof((*arr) * height);
arr[x][y] = 42;
Say you want to dynamically allocate a 2-dimensional integer array of ROWS rows and COLS columns. Then you can first allocate a continuous chunk of ROWS * COLS integers and then manually split it into ROWS rows. Without syntactic sugar, this reads
int *mem = malloc(ROWS * COLS * sizeof(int));
int **A = malloc(ROWS * sizeof(int*));
for(int i = 0; i < ROWS; i++)
A[i] = mem + COLS*i;
// use A[i][j]
and can be done more efficiently by avoiding the multiplication,
int *mem = malloc(ROWS * COLS * sizeof(int));
int **A = malloc(ROWS * sizeof(int*));
A[0] = mem;
for(int i = 1; i < ROWS; i++)
A[i] = A[i-1] + COLS;
// use A[i][j]
Finally, one could give up the extra pointer altogether,
int **A = malloc(ROWS * sizeof(int*));
A[0] = malloc(ROWS * COLS * sizeof(int));
for(int i = 1; i < ROWS; i++)
A[i] = A[i-1] + COLS;
// use A[i][j]
but there's an important GOTCHA! You would have to be careful to first deallocate A[0] and then A,
free(A[0]);
free(A); // if this were done first, then A[0] would be invalidated
The same idea can be extended to 3- or higher-dimensional arrays, although the code will get messy.
You can treat dynamically allocated memory as an array of a any dimension by accessing it in strides:
int * a = malloc(sizeof(int) * N1 * N2 * N3); // think "int[N1][N2][N3]"
a[i * N2 * N3 + j * N3 + k] = 10; // like "a[i, j, k]"
The best way is to allocate a pointer to an array,
int (*a)[cols] = malloc(rows * sizeof *a);
if (a == NULL) {
// alloc failure, handle or exit
}
for(int i = 0; i < rows; ++i) {
for(int j = 0; j < cols; ++j) {
a[i][j] = i+j;
}
}
If the compiler doesn't support variable length arrays, that only works if cols is a constant expression (but then you should upgrade your compiler anyway).
Excuse my lack of formatting or any mistakes, but this is from a cellphone.
I also encountered strides where I tried to use fwrite() to output using the int** variable as the src address.
One solution was to make use of two malloc() invocations:
#define HEIGHT 16
#define WIDTH 16
.
.
.
//allocate
int **data = malloc(HEIGHT * sizeof(int **));
int *realdata = malloc(HEIGHT * WIDTH * sizeof(int));
//manually index
for (int i = 0; i < HEIGHT; i++)
data[i] = &realdata[i * WIDTH];
//populate
int idx = 0;
for (int i = 0; i < HEIGHT; i++)
for (int j = 0; j < WIDTH; j++)
data[i][j] = idx++;
//select
int idx = 0;
for (int i = 0; i < HEIGHT; i++)
{
for (int j = 0; j < WIDTH; j++)
printf("%i, ", data[i][j]);
printf("/n");
}
//deallocate
.
.
.
You can typedef your array (for less headake) and then do something like that:
#include <stdlib.h>
#define N 10
typedef int A[N][N];
int main () {
A a; // on the stack
a[0][0]=1;
A *b=(A*)malloc (sizeof(A)); // on the heap
(*b)[0][0]=1;
}
I am trying to write a function that creates a contiguous block of memory and assigns it to a 3d array. The code works in that it allows me to use the memory, and, when I use data stored in objects created with this function, the results appear correct. However, when I try to free the memory I have allocated with this function, I immediately get a glibc error. Here is the function:
void *** matrix3d(int size, int rows, int cols, int depth) {
void ***result;
int col_size = depth * size;
int row_size = (sizeof(void *) + col_size) * cols;
int data_size = (rows * cols * depth + 1) * size;
int pointer_size = rows * sizeof(void **) + cols * sizeof(void *);
int i, j;
char *pdata, *pdata2;
if((result = (void ***) malloc(pointer_size + data_size)) == NULL)
nerror("ERROR: Memory error.\nNot enough memory available.\n", 1);
pdata = (char *) result + rows * sizeof(void **);
if((long) pdata % (col_size + sizeof(void *)))
pdata += col_size + sizeof(void *) - (long) pdata % (col_size + sizeof(void *));
for(i = 0; i < rows; i++) {
result[i] = pdata;
pdata2 = pdata + cols * sizeof(void *);
for(j = 0; j < cols; j++) {
result[i][j] = pdata2;
pdata2 += col_size;
}
pdata += row_size;
}
return result;
}
It is called in this manner:
double ***positions = (double ***) matrix3d(sizeof(double), numResidues, numChains, numTimesteps);
for(i = 0; i < numResidues; i++)
for(j = 0; j < numChains; j++)
for(k = 0; k < numTimesteps; k++)
positions[i][j][k] = 3.2;
free(positions);
What have I done wrong? Thank you for the help.
What have I done wrong?
Your code is hard to follow (you're playing with pdata a lot) but 99% you're writing past the allocated space and you're messing up the bookkeeping left by glibc.
I can use the data I've written just fine. The only issue is when I
try to use free.
That's because glibc only gets a chance to see you messed up when you call it.
Please excuse my dear Aunt Sally.
int data_size = (rows * cols * depth + 1) * size;
This should be:
int data_size = (rows * cols * (depth + 1)) * size;
Running the code under valgrind identified the error immediately.
What you are doing is one single allocation and then casting it to a tripple-pointer, meaning you have to deal a lot with offsets.
It would probably be better to a larger number of allocations:
char ***result = malloc(sizeof(char **) * rows);
for(i = 0; i < rows; i++) {
result[i] = malloc(sizeof(char *) * cols);
for(j = 0; j < cols; j++) {
result[i][j] = malloc(sizeof(char) * size);
/* Copy data to `result[i][j]` */
}
}
When freeing, you have to free all of the allocations:
for(i = 0; i < rows; i++) {
for(j = 0; j < cols; j++) {
free(result[i][j]);
}
free(result[i]);
}
free(result);
things like this are magnificant candidates to get things wrong
pdata = (char *) result + rows * sizeof(void **);
there is no reason at all to circumvent the address computation that the compiler does for you.