2-D Array of structures -> unable to fix a segmentation fault :( - c

SO (pun intended) I want to solve this question from HackerEarth: https://www.hackerearth.com/practice/data-structures/arrays/multi-dimensional/practice-problems/algorithm/the-wealthy-landlord/
This is my code:
#include <stdio.h>
#define ll long long
int main () {
ll int N;
scanf("%d", &N);
ll int i, j, a, b;
ll int TOTAL;
typedef struct {
ll int flag;
ll int count;
// int fc[N]; // farmer cost OR cost for farmer i
ll int *fc;
} land;
// check whether all of them have been
// initialised to 0
// printf("%d ", arr[2][2].count);
// yes
land arr[1000][1000];
for(i=0; i<1000; i++) {
for(j=0; j<1000; j++) {
arr[i][j].fc = (ll int *)calloc(N, sizeof(ll int));
}
}
ll int x1, y1, x2, y2, c;
ll int ta, tb; // temp a // temp b
for(i=0; i<N; i++) {
scanf("%lld %lld %lld %lld %lld", &x1, &y1, &x2, &y2, &c);
// the array index starts from 0
// so to match the inputs to the correct indices
// the inputs must be reduced by one
for(a=x1; a<=x2; a++) {
for (b=y1; b<=y2; b++) {
ta = a-1;
tb = b-1;
arr[ta][tb].count++;
if(arr[ta][tb].count >= 2)
arr[ta][tb].flag = 1;
arr[ta][tb].fc[i] = c;
}
}
}
ll int k;
for(i=0; i<1000; i++) {
for(j=0; j<1000; j++) {
if (arr[i][j].flag == 1) {
for(k=0; k<N; k++)
TOTAL += arr[i][j].fc[k];
}
}
}
printf("%lld", TOTAL);
return 0;
}
RESULT: Runtime Error (SIGSEGV)
Compilation Log:
Compiled Successfully
Execution Log: Execution failed.Segmentation Fault : This occurs
because of an out-of-scope array index that is causing a buffer
overflow, an incorrectly initialized pointer, etc. A signal is
generated when a program either tries to read or write outside the
memory that is allocated for it or to write memory that can only be
read. For example, you are accessing a[-1] in a language that does not
support negative indices for an array.
I've edited this code multiple times and fixed various issues by looking at various SO questions. Now it is so close to working, but it just makes a straight face and says segmentation fault. The worst kind of fault that gives you little to no hints on how it should be fixed. I am out of ideas!
ALSO - There probably is a better method to solve this problem which does not involve arrays inside a 2-D array of structures, but I would love to learn how to fix this segmentation fault.

Your line: land arr[1000][1000]; declares arr as an automatic variable, which means that space is allocated to it from the stack. Put simply, this stack is memory assigned for local use when a function is called (and main is really just a function called by the operating system when you run the program).
Typically, the amount of space available on the stack is limited - typically 16 - 64 kilobytes. However, your arr variable (assuming 8 bytes for a long long int and 8 bytes for a pointer) will require more than 24 megabytes. This is almost certainly what is causing your "Stack Overflow!"
A 'quick fix' to this problem is to declare the variable static. This means that space is allocated at compile time (or, more likely, at link time) and is 'locked' into memory while the program is running. (You may notice that the size of your executable file increases by 24 MB after you do this - depending on your platform!)
Here is a slightly modified version of your code, with this correction, along with a couple of other suggested improvements (all marked with the "///" comment delimiter:
#include <stdio.h>
#include <stdlib.h>
#define ll long long
int main() {
ll int N;
scanf("%lld", &N); /// The plain "%d" format expects an "int" argument - use "%lld" for "long long int"
ll int i, j, a, b;
ll int TOTAL = 0; /// If you don't INITIALIZE "TOTAL" it could start off with ANY value whatsoever!
typedef struct {
ll int flag;
ll int count;
// int fc[N]; // farmer cost OR cost for farmer i
ll int* fc;
} land;
// check whether all of them have been
// initialised to 0
// printf("%d ", arr[2][2].count);
// yes
static land arr[1000][1000]; /// Without "static" this array (~ 24 Megabytes) will overflow the stack!
for (i = 0; i < 1000; i++) {
for (j = 0; j < 1000; j++) {
arr[i][j].fc = (ll int*)calloc(N, sizeof(ll int));
}
}
ll int x1, y1, x2, y2, c;
ll int ta, tb; // temp a // temp b
for (i = 0; i < N; i++) {
scanf("%lld %lld %lld %lld %lld", &x1, &y1, &x2, &y2, &c);
// the array index starts from 0
// so to match the inputs to the correct indices
// the inputs must be reduced by one
for (a = x1; a <= x2; a++) {
for (b = y1; b <= y2; b++) {
ta = a - 1;
tb = b - 1;
arr[ta][tb].count++;
if (arr[ta][tb].count >= 2)
arr[ta][tb].flag = 1;
arr[ta][tb].fc[i] = c;
}
}
}
ll int k;
for (i = 0; i < 1000; i++) {
for (j = 0; j < 1000; j++) {
if (arr[i][j].flag == 1) {
for (k = 0; k < N; k++)
TOTAL += arr[i][j].fc[k];
}
}
}
printf("%lld", TOTAL);
return 0;
}
Feel free to ask for further clarification and/or explanation.

Related

How to return a double pointer from a function and send it as input into another function?

I am new to programming and am trying to use two functions for matrix (2D array) operations, where the output of one function is the input for the next.
However, I do not find a way to correctly deliver the values from one function to another. When I print the outputs of the first function in main (), they are correct, but when I input them into the 2nd function and print them, the values make no sense. I have tried it a lot of ways, but it probably fails due to my lack of understanding double pointers.
I am thankful for any hint or advise!
#include <stdio.h>
#include <stdlib.h>
int** td (int r_in, int c_in, int r_p, int c_p, int input[][c_in],int params[][c_p]){
int i, j, k;
int**y_td;
// memory allocation
y_td = (int*)malloc(sizeof(int*)*r_in);
for (i=0; i < r_in; i++){
y_td[i] = (int*)malloc(sizeof(int)*c_p);
}
//
for (i=0; i < r_in; i++){
for (j=0; j < c_p; j++){
y_td[i][j]=0; // Initialization
for (k=0; k < c_in; k++){
y_td[i][j]+= input[i][k]*params[k][j];
}
}
}
return y_td;
}
int** cnv (int r_in, int c_in, int filter, int f_size, int input[][c_in], int params[][f_size][c_in]){
int x,i,j,k,l,m,n;
int min_len = ((r_in < f_size)? r_in:f_size);
int max_len = ((r_in > f_size)? r_in:f_size);
int r_out = max_len - min_len + 1;//rows_out
int kernel;
int** y_cnv;
// Print input to check if it was correctly transmitted to the function
printf("Input CV (should be equal to TD result):\n");
for (i=0;i<r_in;i++){
for (j=0;j<c_in;j++){
printf("%d ", input[i][j]);
}
printf("\n");
}
printf("\n\n");
//memory allocation
y_cnv = (int*)malloc(sizeof(int*)*r_out);
for (i=0; i < r_out; i++){
y_cnv[i] = (int*)malloc(sizeof(int)*filter);
}
//
for (i=0; i < filter; i++){
for (k=0; k < r_out; k++){
y_cnv [k][i]=0; //initialize
}
for (j = 0; j < c_in; j++){
for (n = min_len-1; n < max_len; n++){
x = n-min_len+1;
for (m= 0; m < r_in; m++){
kernel = (((n-m) < min_len && (n-m) >= 0)? params[i][n-m][j]:0);
y_cnv[x][i] += input[m][j]*kernel;
}
}
}
}
return y_cnv;
}
int main() {
// create test arrays
int A [4][2]= {{1,1},{2,2},{3,3},{4,4}};
int B [2][3]= {{1,2,3},{2,3,4}};
int C [2][2][3]= {{{1,1,1},{2,2,2}},{{3,3,3},{4,4,4}}};
int** matrix;
int i, j;
matrix = td(4,2,2,3,A,B);
// print the result of first function, which is input in 2nd function
printf("The TD result is:\n");
for (i=0;i<4;i++){
for (j=0;j<3;j++){
printf("%d ",matrix[i][j]);
}
printf("\n");
}
printf("\n\n");
matrix = cnv(4,3,2,2,matrix,C);
return 0;
}
I expect the matrix printed in main () after the first function td () to be the same as when I read it in the second function cnv () and print it there, but it is not.
take a look at this question. You were hit by the same underlying problem.
Turning
int** cnv (int r_in, int c_in, int filter, int f_size, int input[][c_in], int params[][f_size][c_in])
into
int** cnv (int r_in, int c_in, int filter, int f_size, int** input, int params[][f_size][c_in])
fixes the problem you asked for.
The reason is that you allocate an array of pointers called y_td in your first function. Each of this pointers is a number naming a memory segment where you stored some real numbers. By using int input[][c_in] you tell the computer to interpret these pointers as integer numbers and when you print them you get the addresses in memory instead of the expected values, because then input[x][y] is translated to *((int *)input+x*c_in+y).
Please allow me one more comment: You should follow the comments below the question and care for all compiler warnings: If there is a warning you should treat it as an compiler error unless you exactly know what you are doing, especially in C. Your code contains some possible problem sources like the one above.

Different error messages while freeing allocated memory

I created a struct, called ArrayCount, that contains a double array and an integer that should count how often an array occurs.
If the size of the double-array is n, the idea is, to create an array of the struct ArrayCount of the size n! (n! is called m in my code).
The idea is to safe each permutation in the ArrayCount-array, counting the occurrences of each permutation, for a given algorithm. But that's just the background information and not part of the problem.
I am having issues while freeing the memory that was allocated for the double-Arrays.
Oddly enough, ~ 1/10 times my code compiles without an error message and sometimes different error messages appear.
error message:
munmap_chunk(): invalid pointer
Aborted (core dumped)
error message:
free(): invalid size
Aborted (core dumped)
error message:
Segmentation fault (core dumped)
Part of the code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
double* array_copy(const double* a, int n) {
srand(time(NULL));
double* copy = calloc(n, 8);
for(int i = 0; i < n; i++) {
copy[i] = a[i];
}
return copy;
}
void shuffle(double* a, int n) {
for(int i = n - 1; i >= 0; i--) {
time_t t;
/* Intializes random number generator */
srand((unsigned) time(&t));
double* copy = array_copy(a, i + 1);
//Generates random numbers in the closed intervall [0,i].
int random = rand() % (i + 1);
a[i] = a[random];
a[random] = copy[i];
free(copy);
}
}
// Refers to a double array and counts how often this array has
occurred yet.
typedef struct {
double* array;
int counter;
} ArrayCount;
// Computes the factorial of n: n!.
int factorial(int n) {
int result = 1;
for (int i = 2; i <= n; i++) {
result *= i;
}
return result;
}
/*
Saves all permutations in array_counts, for a given double array of
the length n and counts how often each permutations occurs.
(Hint given by our supervisor: Save a copy of a in array_counts)
*/
void update_array_counts(/*INOUT*/ ArrayCount* array_counts, int m,
/*IN*/ const double* a, int n) {
double* copy_a = array_copy(a, n);
//Increases the counter by 1, if a is already listed in
array_counts
for(int i = 1; i <= m; i++) {
int count = 0;
for(int j = 0; j < n; j++) {
if(array_counts[i].array[j] == a[j]) count++;
}
if(count == n) {
array_counts[i].counter++;
free(copy_a);
return;
}
}
//Saves a in array_counts and sets the counter to 1, if a is not
listed in array_counts, yet
for(int i = 1; i <= m; i++) {
int count = 0;
for(int j = 0; j < n; j++) {
if(array_counts[i].array[j] == 0) count++;
}
if(count == n) {
for(int j = 0; j < n; j++) {
array_counts[i].array[j] = a[j];
}
array_counts[i].counter = 1;
free(copy_a);
return;
}
}
}
// Gibt die Häufigkeit der verschiedenen Permutationen eines Arrays
der Länge n aus.
void shuffle_frequency(int n) {
double a[n];
for (int i = 0; i < n; i++) {
a[i] = i;
}
int m = factorial(n);
ArrayCount* array_counts = calloc(m, sizeof(ArrayCount));
for(int i = 1; i <= m; i++){
array_counts[i].array = calloc(n, sizeof(double));
}
for (int i = 0; i < 1000 * m; i++) {
shuffle(a, n);
update_array_counts(array_counts, m, a, n);
}
for (int i = 1; i <= m; i++) {
printf("%4d%8d ", i, array_counts[i].counter);
}
//The next free-statement is causing problems.
for(int i = 1; i <= m; i++) {
printf("i = %d\n", i);
free(array_counts[i].array);
}
free(array_counts);
}
int main(void) {
shuffle_frequency(4);
return 0;
}
What am I doing wrong?
I am having issues while freeing the memory that was allocated for the
double-Arrays. Oddly enough, ~ 1/10 times my code compiles without an
error message and sometimes different error messages appear.
complies without error message or runs without error message? I see runtime errors ( Segfault or Abort signals, to be exact ) not compile time. kl
for (int i = 1; i <= m; i++) {
The correct way to iterate through an array of m elements is
for(int i=0; i < m; i++){
As pointed out in the comments, offsets start at 0 and to to m-1, not m. That makes free(array_counts[i].array) becomes free(array_counts[m].array) What's at array_counts[m]? Could be various things, which might be deterministic or nondeterministic at runtime, but it is outside the memory you allocated. Behavior of free is undefined in this case, as it is whenever passed an address that wasn't allocated with malloc and friends.
Consider http://man7.org/linux/man-pages/man3/malloc.3.html, a copy of the manpage for free:
The free() function frees the memory space pointed to by ptr, which
must have been returned by a previous call to malloc(), calloc(), or
realloc(). Otherwise, or if free(ptr) has already been called
before, undefined behavior occurs.

OpenMP segmentation fault

recently I am working on a c OpenMP code which carrying out the affinity scheduling. Basically, after a thread has finished its assigned iterations, it will start looking for other threads which has the most work load and steal some jobs from them.
Everything works fine, I can compile the file using icc. However, when I try to run it, it gives me the segmentation fault(core dumped). But the funny thing is, the error is not always happen, that is, even I get an error when I first run the code, when I try to run again, sometimes it works. This is so weird to me. I wonder what I did wrong in my code and how to fix the problem. Thank you. I did only modified the method runloop and affinity, others are given at the beginning which works fine.
#include <stdio.h>
#include <math.h>
#define N 729
#define reps 1000
#include <omp.h>
double a[N][N], b[N][N], c[N];
int jmax[N];
void init1(void);
void init2(void);
void runloop(int);
void loop1chunk(int, int);
void loop2chunk(int, int);
void valid1(void);
void valid2(void);
int affinity(int*, int*, int, int, float, int*, int*);
int main(int argc, char *argv[]) {
double start1,start2,end1,end2;
int r;
init1();
start1 = omp_get_wtime();
for (r=0; r<reps; r++){
runloop(1);
}
end1 = omp_get_wtime();
valid1();
printf("Total time for %d reps of loop 1 = %f\n",reps, (float)(end1-start1));
init2();
start2 = omp_get_wtime();
for (r=0; r<reps; r++){
runloop(2);
}
end2 = omp_get_wtime();
valid2();
printf("Total time for %d reps of loop 2 = %f\n",reps, (float)(end2-start2));
}
void init1(void){
int i,j;
for (i=0; i<N; i++){
for (j=0; j<N; j++){
a[i][j] = 0.0;
b[i][j] = 3.142*(i+j);
}
}
}
void init2(void){
int i,j, expr;
for (i=0; i<N; i++){
expr = i%( 3*(i/30) + 1);
if ( expr == 0) {
jmax[i] = N;
}
else {
jmax[i] = 1;
}
c[i] = 0.0;
}
for (i=0; i<N; i++){
for (j=0; j<N; j++){
b[i][j] = (double) (i*j+1) / (double) (N*N);
}
}
}
void runloop(int loopid)
{
int nthreads = omp_get_max_threads(); // we set it before the parallel region, using opm_get_num_threads() will always return 1 otherwise
int ipt = (int) ceil((double)N/(double)nthreads);
float chunks_fraction = 1.0 / nthreads;
int threads_lo_bound[nthreads];
int threads_hi_bound[nthreads];
#pragma omp parallel default(none) shared(threads_lo_bound, threads_hi_bound, nthreads, loopid, ipt, chunks_fraction)
{
int myid = omp_get_thread_num();
int lo = myid * ipt;
int hi = (myid+1)*ipt;
if (hi > N) hi = N;
threads_lo_bound[myid] = lo;
threads_hi_bound[myid] = hi;
int current_lower_bound = 0;
int current_higher_bound = 0;
int affinity_steal = 0;
while(affinity_steal != -1)
{
switch(loopid)
{
case 1: loop1chunk(current_lower_bound, current_higher_bound); break;
case 2: loop2chunk(current_lower_bound, current_higher_bound); break;
}
#pragma omp critical
{
affinity_steal = affinity(threads_lo_bound, threads_hi_bound, nthreads, myid, chunks_fraction, &current_lower_bound, &current_higher_bound);
}
}
}
}
int affinity(int* threads_lo_bound, int* threads_hi_bound, int num_of_thread, int thread_num, float chunks_fraction, int *current_lower_bound, int *current_higher_bound)
{
int current_pos;
if (threads_hi_bound[thread_num] - threads_lo_bound[thread_num] > 0)
{
current_pos = thread_num;
}
else
{
int new_pos = -1;
int jobs_remain = 0;
int i;
for (i = 0; i < num_of_thread; i++)
{
int diff = threads_hi_bound[i] - threads_lo_bound[i];
if (diff > jobs_remain)
{
new_pos = i;
jobs_remain = diff;
}
}
current_pos = new_pos;
}
if (current_pos == -1) return -1;
int remaining_iterations = threads_hi_bound[current_pos] - threads_lo_bound[current_pos];
int iter_size_fractions = (int)ceil(chunks_fraction * remaining_iterations);
*current_lower_bound = threads_lo_bound[current_pos];
*current_higher_bound = threads_lo_bound[current_pos] + iter_size_fractions;
threads_lo_bound[current_pos] = threads_lo_bound[current_pos] + iter_size_fractions;
return current_pos;
}
void loop1chunk(int lo, int hi) {
int i,j;
for (i=lo; i<hi; i++){
for (j=N-1; j>i; j--){
a[i][j] += cos(b[i][j]);
}
}
}
void loop2chunk(int lo, int hi) {
int i,j,k;
double rN2;
rN2 = 1.0 / (double) (N*N);
for (i=lo; i<hi; i++){
for (j=0; j < jmax[i]; j++){
for (k=0; k<j; k++){
c[i] += (k+1) * log (b[i][j]) * rN2;
}
}
}
}
void valid1(void) {
int i,j;
double suma;
suma= 0.0;
for (i=0; i<N; i++){
for (j=0; j<N; j++){
suma += a[i][j];
}
}
printf("Loop 1 check: Sum of a is %lf\n", suma);
}
void valid2(void) {
int i;
double sumc;
sumc= 0.0;
for (i=0; i<N; i++){
sumc += c[i];
}
printf("Loop 2 check: Sum of c is %f\n", sumc);
}
You don't initialise the arrays threads_lo_bound and threads_hi_bound, so they initially contain some completely random values (this is source of randomness number 1).
You then enter the parallel region, where it is imperative to realise not all threads will be moving through the code in sync, the actual speed of each threads is quite random as it shares the CPU with many other programs, even if they only use 1%, that will still show (this is source of randomness number 2, I'd argue this one is more relevant to why you see it working every now and then).
So what happens when the code crashes?
One of the threads (most likely the master) reaches the critical region before at least one of the other threads has reached the line where you set threads_lo_bound[myid] and threads_hi_bound[myid].
After that, depending on what those random values stored in there were (you can generally assume they were out of bounds, your array is fairly small, the odds of those values being valid indices are pretty slim), the thread will try to steal some of the jobs (that don't exist) by setting current_lower_bound and/or current_upper_bound to some value that is out of range of your initial arrays a, b, c.
It will then enter the second iteration of your while(affinity_steal != -1) loop and access memory that is out of bounds inevitably leading to a segmentation fault (eventually, in principle it's undefined behaviour and the crash can occur at any point after an invalid memory access, or in some cases never, leading you to believe everything is in order, when it is most definitely not).
The fix of course is simple, add
#pragma omp barrier
just before the while(affinity_steal != -1) loop to ensure all threads have reached that point (i.e. synchronise the threads at that point) and the bounds are properly set before you proceed into the loop. The overhead of this is minimal, but if for some reason you wish to avoid using barriers, you can simply set the values of the array before entering the parallel region.
That said, bugs like this can usually be located using a good debugger, I strongly suggest learning how to use one, they make life much easier.

Dealing with big sized array in c programming

I am working on nonlinear differential equation.
What I was doing is to average up the positions over 100 different values of initial conditions.
I used odeiv in gsl. For each initial values, the time range is 4*10^7. However, the program kills, once ever I set 10 different initial conditions and the time range 10^6. This is kind of limit.
My computer has 8 cores and 16GB memory. I don't think this is that much big.
I'll put a part of the coding. Anybody help me on this?
Thank you.
long long int i, j, k;
double const y_i = 0, dydt_i = 0;
double n = 10;
long long int tmax = 1000000;
double A[tmax];
for (j=0; j < n; j++)
{
double y_j = y_i + 0.001*j;
double dydt_j = dydt_i;
t = 0.0;
double y[2] = {y_j, dydt_j};
gsl_odeiv2_system sys = {func, jac, 2, &params};
gsl_odeiv2_driver * d = gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rk8pd, 1e-6, 1e-6, 0.0);
for (i=0; i< tmax; i++)
{
double ti = (double) i;
int status = gsl_odeiv2_driver_apply (d, &t, ti, y);
if (status != GSL_SUCCESS)
{
printf("error, return value%d\n", status);
break;
}
A[i] = A[i] +y[0];
}
gsl_odeiv2_driver_free (d);
}
for (k=0; k < tmax; k++)
{
A[k] = A[k]/n;
printf("%lld %e\n", k, A[k]);
}
return 0;
}
}
Local variables are allocated on the stack; the stack is not particularly huge, which means it's a bad place to allocate very large arrays. You need to make A a pointer and allocate it dynamically (or better, make it std::vector<double> if C++ is an option).

How to set array B[0..n][0..k]. Help Please

I have to implement code to find the Binomial Coefficient using dynamic programming. But I don't know how to set the array B. Here the code I have:
#include <stdio.h>
int minimum(int a, int b) { return (a < b) ? a : b; }
main() {
int n = 50, k;
printf("Enter value for k:");
scanf("%d", &k);
printf("Value of coefficient %d, %d is: %d\n", n, k, bin2(n, k));
return 0;
}
// code to be implemented
int bin2(int n, int k) {
int i, j;
// array to initialize. Help
int B[0..n][0..k];
for (i = 0; i <= n; i++)
for (j = 0; j <= minimum(i, k); j++)
if (j == 0 || j == i)
B[i][j] = 1;
else
B[i][j] = B[i - 1][j - 1] + B[i - 1][j];
return B[n][k];
}
You can use the malloc() and calloc() functions from <stdlib.h> to allocate memory on the fly. Since you want to be able to store indices from 0 to n and 0 to k, you have to create a (n+1) × (k+1) array. This is done by allocating an array of n+1 int* pointers, then assigning an array of k+1 int values to each pointer:
/* Initialize array */
B = malloc((n+1) * sizeof(int*));
for (i=0; i<=n; i++) B[i] = calloc((k+1), sizeof(int));
When your function exits, this memory will still be allocated, but you will no longer be able to access it because the value of B is local to the bin2() function and will be lost forever. (This is called a memory leak.)
So you need to free up this memory before returning:
int result = B[n][k];
/* Dispose of array */
for (i=0; i<=n; i++) free(B[i]);
free(B);
return result;
}
(By the way, this isn't dynamic programming you're asking about, it's dynamic memory allocation. And there are better ways of calculating binomial coefficients.)

Resources