Getting value from dynamically allocated 2D array - c

I'm new to C programming so I am probably doing something really stupid here. I am trying to get the value from a 2D array that I read in from a text file ~70m lines.
When running the code, I get a seg fault and I have narrowed it down to line 10: if (i == graph[j][0])
void convertToCSR(int source, int maxNodes, int maxEdges, int* vertices, int* edges, int** graph) {
int i;
int j;
int edge = 0;
for (i = 0; i < maxNodes; i++) {
vertices[i] = edge;
for (j = 0; j < maxEdges; j++) {
if (i == graph[j][0]) {
//Sets edges[0] to the first position
edges[edge] = graph[j][1];
printf("new edge value: %d\n", edge);
edge++;
}
}
}
vertices[maxNodes] = maxEdges;}
I have tried this with smaller datasets e.g 50 bytes and it works fine. With further testing, I print out the value of graph[0][0] and I get a seg fault.
The graph has loaded the data and was allocated like this:
int num_rows = 69000000;
graph = (int**) malloc(sizeof(int*) * num_rows);
for(i=0; i < num_rows; i++){
graph[i] = (int*) malloc(sizeof(int) * 2 );
}
I am also able to get the value of graph[0][0] outside of this method but not inside.What am I doing wrong? I appreciate any help.
EDIT: In my main method, I am doing the following:
readInputFile(file);
int source = graph[0][0];
convertToCSR(source, maxNodes, maxEdges, nodes, edges, graph);
I have the correct value for the variable : source.
It seg faults in the convertToCSR method.

You’re using num_rows to store a number bigger than int capacity.
So the actual value int num_rows is not 69000000, because of the Overflow.
Try to use long unsigned int num_rows instead.

Related

Why doesn't my function work using structures in C?

I am creating an array that contains the locations of sites in space. So for array[2], I also want to say array[2].num = 2 I want each site to have a unique site number num from 0 to N-1. Output different values of i for array[i].num gives 0, 1, 32767. Whereas, for increasing i, I want to see incrementing values from 0 to N-1.
I am very new to structures so if you could explain where I am making my mistakes I would much appreciate your help as a noice programmer.
typedef struct site_t
{
int num; // want to add more varaibels later hence type struct //
} site;
site fillStruct( site[], int);
int main()
{ int i;
const int N = 20;
site array[N];
fillStruct(array, N);
for (i = 0; i < N; i++) {
printf("location of site %d\n", array[i].num);
}
}
site fillStruct(site array[], int size) {
for (int k = 0; k < size; k++) {;
array[k].num = k;
return array[k];
}
}
If I'm understanding your question correctly, I think your problem comes from your fillStruct() function. The loop in this function will only execute once, instead of N times. You never exceed k=0, so you set the num member for array[0] and then return array[0].
When you return to your main function, you print the location for array[0] accurately, but subsequent site numbers in the array are just random uninitialized values.
Instead, you want the return statement to be outside of the loop block, so the function should like like...
site fillStruct(site array[], int size) {
int k;
for (k = 0; k < size; k++) {;
array[k].num = k;
}
return array[k-1]; // Returns the last site in the array
}
Now, when you return to your main function you will have 20 sites numbered 0 to 19 (for N=20).
Also note that in the code you gave, you are not using the return value of fillStruct().
Hope that helps, let me know if I missed something.

Issue with dynamic memory allocation in C

I am trying to implement a sort function (counting sort, it is probably wrong):
void countingsortmm(int* numbers, int len, int min, int max) {
printf("Sorting %d integers with the min: %d and max: %d\n",len,min,max);
int countLen = max-min+1;
/* create an array to store counts for the occurences of a number. */
int* countingArray = (int*)malloc(countLen);
/* init all values to 0 */
for(int i = 0; i < countLen; i++) countingArray[i] = 0;
/* increment at indexes where a number occurs */
for(int i = 0; i < len; i++) countingArray[numbers[i]]++;
/* add previous indexes */
for(int i = 1; i < countLen; i++) countingArray[i] += countingArray[i-1];
/* Array where numbers will be places in a sorted order. */
int* sortedArray = (int*)malloc(len);
/* put numbers in proper place in new array and decrement */
for(int i = len-1; i >= 0; i--) sortedArray[countingArray[numbers[i]]--] = numbers[i];
/* copy contents of new sorted array to the numbers parameter. */
for(int i = 0; i < len-1; i++) numbers[i] = sortedArray[i];
free(sortedArray);
free(countingArray);
}
But I get the following error:
malloc: *** error for object 0x7f8728404b88: incorrect checksum for freed object - object was probably modified after being freed.
I get a break-point at int* sortedArray = (int*)malloc(len);.
I use malloc() twice to create two different arrays within the function and I free() them both at the end of the function when they are no longer needed. I do not explicitly modify or access their contents afterwards.
So what is causing this problem?
It means you're corrupting your heap. Perhaps you meant malloc(countLen * sizeof(int)); and malloc(len * sizeof(int));? malloc takes its size in bytes.

How to populate a bidimensional array in the reverse way - C

I'm trying to populate a bidimensional array in the reverse way but I'm getting always the same error: core dump.
When I say reverse way I mean, usually we do something like
for(int i=0; i<MaxColumns; i++)
for(int b=0; i<MaxRows; b++)
array[i][b] = random value;
What I'm trying to do is for each row, I want to populate that single row on every column and then pass to the next row and do the same. At this time I'm declaring dynamically a new row for each column.
This is what I was trying:
int i = atoi(argv[1]);
int **array = (int**)malloc(i * sizeof(int*));
for (lines =0; lines <MAXLINES; lines ++) {
for (colunms =0; colunms <i; colunms ++) {
array[colunms] = (int*)malloc(1 * sizeof(int));
v=colunms+lines;
array[colunms][lines]=v;
}
}
And the error goes on:
array[colunms][lines]=v;
------ LAST UPDATE TO PROBLEM ----
Already updated and although I tried this code
for (lines =0; lines <MAXLINES; lines ++) {
array[colunms] = (int*)malloc(colunms * sizeof(int));
for (colunms =0; colunms <i; colunms ++) {
v=colunms+lines;
array[colunms][lines]=v;
}
}
I keep getting core dumped on:
array[colunms][lines]=v;
Thats simple enough. Instead of:
for(int i=0; i<MaxColumns; i++)
for(int b=0; i<MaxRows; b++)
array[i][b]=random value;
Use:
for(int b=0; i<MaxRows; b++)
for(int i=0; i<MaxColumns; i++)
array[i][b]=random value;
Your error though is in:
array[colunms] = (int*)malloc(1 * sizeof(int));
You are allocating space for 1 element of int where you should be allocating for colunms * sizeof(int). You should also do that outside the inner loop, like this:
int **array = (int**)malloc(MAXLINES * sizeof(int*));
for (lines =0; lines <MAXLINES; lines ++) {
array[lines] = (int*)malloc(i * sizeof(int));
for (colunms =0; colunms <i; colunms ++) {
v=colunms+lines;
array[lines][colunms] = v;
}
}
Also, even though this code should work, it can be a problem in the future to assume this as array[colunms][lines] where it should be array[lines][colunms].
Why? Because with array[lines][colunms] each array[line] represents a complete row with all its columns, which is a lot more practical for most cases.
In this form you will be able to declare functions to handle single records instead of handing it the entire "table".

Working with big float data in C

I want to do some calculation with some matrices whose size is 2048*2048, for example.But the simulator stop working and it does not simulate the code. I understood that the problem is about the size and type of variable. For example, I run a simple code, which is written below, to check whether I am right or not. I should print 1 after declaring variable A. But it does not work.
Please note that I use Codeblocks. WFM is a function to write a float matrix in a text file and it works properly because I check that before with other matrices.
int main()
{
float A[2048][2048];
printf("1");
float *AP = &(A[0][0]);
const char *File_Name = "example.txt";
int counter = 0;
for(int i = 0; i < 2048; i++)
for(int j = 0; j < 2048; j++)
{
A[i][j] = counter;
++counter;
}
WFM(AP, 2048, 2048, File_Name , ' ');
return 0;
}
Any help and suggestion to deal with this problem and larger matrices is appreciate it.
Thanks
float A[2048][2048];
which requires approx. 2K * 2K * 8 = 32M of stack memory. But typically the stack size of the process if far less than that. Please allocate it dynamically using alloc family.
float A[2048][2048];
This may be too large for a local array, you should allocate memory dynamically by function such as malloc. For example, you could do this:
float *A = malloc(2048*2048*sizeof(float));
if (A == 0)
{
perror("malloc");
exit(1);
}
float *AP = A;
int counter = 0;
for(int i = 0; i < 2048; i++)
for(int j = 0; j < 2048; j++)
{
*(A + 2048*i + j) = counter;
++counter;
}
And when you does not need A anymore, you can free it by free(A);.
Helpful links about efficiency pitfalls of large arrays with power-of-2 size (offered by #LưuVĩnhPhúc):
Why is transposing a matrix of 512x512 much slower than transposing a matrix of 513x513?
Why is my program slow when looping over exactly 8192 elements?
Matrix multiplication: Small difference in matrix size, large difference in timings

C matrix function segmentation fault

I have this piece of code that gives me SEGMENTATION FAULT when the function loadRow(tmpPop,bestOf4Route,k,n); is called the fifth time. In particular, the function is called correctly at the first loop of the fro (when p=3). It' all ok for every value of k. I don't understand why, the second time I execute the loop (p=7), the first time is called (k=0), it return SEGMENTATION F when try to access the matric tmpPop.
randperm(popSize,randomOrder);
for(p = 3;p<popSize;p+=4)
{
load_rtes(rtes,pop,randomOrder,n,p);
load_dists(dists,totalDist,randomOrder,p);
find_min(dists, 4,&m,&idx);
for(j=0;j<n;j++) bestOf4Route[j]=rtes[j][idx];
X = rand_range(1,5);
Y = rand_range(1,5);
for(k =0;k<4;k++) //Mutate the Best to get Three New Routes
{
loadRow(tmpPop,bestOf4Route,k,n);
switch(k)
{
case 1: //Flip
flipMutation(tmpPop,k,X,Y);
break;
case 2: //Swap
swapMutation(tmpPop,k,X,Y);
break;
case 3: //Slide
slideMutation(tmpPop,k,X,Y);
break;
}
}
loadnewPop(newPop,tmpPop,p,n);
}
The function is:
void loadRow(int **mat,int *array,int k,int size)
{
int j;
for(j=0;j<size;j++)
{
mat[j][k] = array[j];
}
}
The parameters are:
popSize = 16
n= 8
// create 4 x N matrix
tmpPop = (int**)malloc(n * sizeof(int*));
if(tmpPop==NULL) return 1;
for (i = 0; i < n; i++) {
tmpPop[i] = (int*)malloc(4 * sizeof(int));
if(tmpPop[i]==NULL) return 1;
}
// Creates an array of n
bestOf4Route = (int*)malloc(n * sizeof(int));
if(bestOf4Route==NULL) return 1;
clear_array(bestOf4Route,n);
And her it is the debug result:
00401865 loadRow(mat=0x3e1438, array=0x3e1698, k=0, size=8)
void load_rtes(int **rtes,int **pop,int *randomOrder, int n,int p)
{
int i,j,r;
for(i=p-3;i<=p;i++)
{
//thakes the i element of randomOrder and use it as index for the pop row
r=randomOrder[i];
// copy the pop row in rtes
for(j=0;j<n;j++)
{
rtes[j][i]=pop[j][r];
}
}
}
void randperm(int n,int *perm)
{
int i, j, t;
for(i=0; i<n; i++)
perm[i] = i;
for(i=0; i<n; i++) {
j = rand()%(n-i)+i;
t = perm[j];
perm[j] = perm[i];
perm[i] = t;
}
}
A Segfault means that you accessed a memory region you weren't allowed to access. This can happen quite easily when doing pointer arithmetic wrong. So, although I can't tell you where the problem exactly lies, I suggest that you use a good debugger or some printf() statements to look at k, n and j to see if you exceed the bounds of the matrix / array. Also, you'll need to make sure that you allocated the right amount of memory.

Resources