This question already has answers here:
Why do I get a segfault in C from declaring a large array on the stack?
(5 answers)
Closed 3 years ago.
I am learning C and trying new things to test what I can do. I have written code which produces a Mandelbrot set with a given resolution (RES) which is #define RES in the .h file. This works and produces good output for resolutions less than 321. For some reason when RES > 321 then the code no longer executes.
I am running using GCC and plotting the output using Gnuplot. I have tried debugging with a debugger however for RES > 321 the main function no longer gets run? I have added a print in the first line of main() to see and this doesn't get run. An executable is made and the program compiles with no errors?
#include <stdio.h>
#include <math.h>
#define MAX_DEPTH 100
#define RES 321
typedef struct complex_t {
double re;
double im;
} complex;
void init_complex_grid(complex complex_grid[RES][RES], double left, double right, double top, double bottom);
int converge(complex a);
complex add_complex(complex a, complex b);
complex square_complex(complex a);
double mag_complex(complex a);
void output_grid(unsigned int grid[RES][RES]);
int main(void) {
// printf("HERE\n");
int i, j;
unsigned int convergence_grid[RES][RES];
complex complex_grid[RES][RES];
init_complex_grid(complex_grid, -2.5, 1, 1, -1);
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
convergence_grid[i][j] = converge(complex_grid[i][j]);
}
}
output_grid(convergence_grid);
return 0;
}
void init_complex_grid(complex complex_grid[RES][RES],
double left, double right,
double top, double bottom) {
int i, j;
double restep = (top - bottom) / RES;
double imstep = (right - left) / RES;
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
complex_grid[i][j].re = left + j * imstep;
complex_grid[i][j].im = bottom + i * restep;
}
}
}
int converge(complex a) {
complex z = { 0, 0 };
int cnt = 0;
while (cnt <= MAX_DEPTH && mag_complex(z) <= 2) {
z = add_complex(square_complex(z), a);
cnt++;
}
return cnt;
}
complex add_complex(complex a, complex b) {
complex added = { a.re + b.re, a.im + b.im };
return added;
}
complex square_complex(complex a) {
complex b;
b.re = a.re * a.re - a.im * a.im;
b.im = 2 * a.re * b.im;
return b;
}
double mag_complex(complex a) {
return sqrt(a.re * a.re + a.im * a.im);
}
void output_grid(unsigned int grid[RES][RES]) {
FILE *f = fopen("mandelbrot.dat", "w");
int i, j;
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
fprintf(f, "%d ", grid[i][j]);
}
fprintf(f, "\n");
}
fclose(f);
printf("\nFILE CLOSED\n");
}
I also added the line printf("\nFILE CLOSED\n"); so I would know that the output had been written to the file but this does not get run either with RES > 321.
You are defining too much data with automatic storage in the main() function: either make the large arrays global, static or allocate them from the heap.
Here is a simple fix you can try:
int main(void) {
int i, j;
static unsigned int convergence_grid[RES][RES];
static complex complex_grid[RES][RES];
init_complex_grid(complex_grid, -2.5, 1, 1, -1);
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
convergence_grid[i][j] = converge(complex_grid[i][j]);
}
}
output_grid(convergence_grid);
return 0;
}
Here is an alternative using heap allocation:
int main(void) {
int i, j;
unsigned int (*convergence_grid)[RES] = calloc(sizeof(*convergence_grid), RES);
complex (*complex_grid)[RES] = calloc(sizeof(*complex_grid), RES);
if (!convergence_grid || !complex_grid) {
fprintf(stderr, "cannot allocate arrays\n");
return 1;
}
init_complex_grid(complex_grid, -2.5, 1, 1, -1);
for (i = 0; i < RES; i++) {
for (j = 0; j < RES; j++) {
convergence_grid[i][j] = converge(complex_grid[i][j]);
}
}
output_grid(convergence_grid);
free(complex_grid);
free(convergence_grid);
return 0;
}
Related
I am trying to make a zoom_image function which zooms gray image using discrete Fourier transform,. the code i am include work if the image size is less than or equal 4*4 but if size increase. it gives 'double free or corruption (out) Aborted (core dumped)' error
I have tried fft_d and ifft_2d function of my code it works if input size is small if input size is big it gives the above error
#include<math.h>
#include<stdio.h>
#include<stdlib.h>
struct complex{
float real;
float im;
};
typedef struct complex complex;
complex w(int i, int n) {
complex result;
result.real = cos(2*M_PI*i/n);
result.im = -sin(2*M_PI*i/n);
return result;
}
complex wp(int i, int n) {
complex result;
result.real = cos(2*M_PI*i/n);
result.im = sin(2*M_PI*i/n);
return result;
}
complex mul(complex a, complex b) {
complex result;
result.real = a.real*b.real - a.im*b.im;
result.im = a.real*b.im + b.real*a.im;
return result;
}
complex divi(complex a, complex b) {
complex result;
result.real = (a.real*b.real + a.im*b.im)/(b.real*b.real + b.im*b.im);
result.im = (-a.real*b.im + b.real*a.im)/(b.real*b.real + b.im*b.im);
return result;
}
complex add(complex a, complex b) {
complex result;
result.real = a.real+b.real ;
result.im = a.im+b.im;
return result;
}
complex sub(complex a, complex b) {
complex result;
result.real = a.real - b.real;
result.im = a.im - b.im;
return result;
}
void printComplex(complex var) {
printf("%f i%f\n",var.real,var.im);
}
void printComplexS(complex var) {
printf("%f i%f",var.real,var.im);
}
#include<stdio.h>
#include<stdlib.h>
#include"complex.h"
static int gb=0;
complex* _fft(complex *arr, int size, int step, int index) {
if(size == 2) {
complex *result;
result = (complex*)malloc(size*sizeof(complex));
result[0] = add(arr[index], arr[index+step]);
result[1] = sub(arr[index], arr[index+step]);
return result;
}
else {
int i;
complex *even, *odd, *result, *mull;
even = _fft(arr, size/2, step*2, index);
odd = _fft(arr, size/2, step*2, index+step);
result = (complex*)malloc(size*sizeof(complex));
mull = (complex*)malloc(size/2*sizeof(complex));
for(i=0;i<size/2;i++) {
mull[i] = mul(odd[i], w(i,size));
}
for(i=0;i<size/2;i++)
result[i] = add(even[i], mull[i]);
for(;i<size;i++)
result[i] = sub(even[i - size/2], mull[i - size/2]);
free(even);
free(odd);
free(mull);
return result;
}
}
complex* fft(complex *arr, int size) {
return (complex*)_fft(arr, size, 1, 0);
}
complex* _ifft(complex *arr, int size, int step, int index) {
if(size == 2) {
complex *result;
result = (complex*)malloc(size*sizeof(complex));
result[0] = add(arr[index], arr[index+step]);
result[1] = sub(arr[index], arr[index+step]);
return result;
}
else {
int i;
complex *even, *odd, *result, *mull;
even = _ifft(arr, size/2, step*2, index);
odd = _ifft(arr, size/2, step*2, index+step);
result = (complex*)malloc(size*sizeof(complex));
mull = (complex*)malloc(size/2*sizeof(complex));
for(i=0;i<size/2;i++)
mull[i] = mul(odd[i], wp(i,size));
for(i=0;i<size/2;i++)
result[i] = add(even[i], mull[i]);
for(;i<size;i++)
result[i] = sub(even[i - size/2], mull[i - size/2]);
free(even);
free(odd);
free(mull);
return result;
}
}
complex* ifft(complex *arr, int size) {
complex *re = _ifft(arr, size, 1, 0);
for(int i=0;i<size;i++){
re[i].real=re[i].real/size;
re[i].im=re[i].im/size;
}
return re;
}
complex** transpose(complex **src, int n, int m) {
complex **result, ***re;
result=(complex**)malloc(sizeof(complex*)*m);
for(int i=0;i<m;i++) {
result[i]=(complex*)malloc(sizeof(complex)*n);
for(int j=0;j<n;j++)
result[i][j]=src[j][i];
}
re=(complex***)&result;
return (complex**)*re;
}
complex** fft_2d(complex** arr, int n, int m) {
complex **arrR, ***r, *temp;
int i, j;
arrR = (complex**)malloc(sizeof(complex*));
for(i=0;i<n;i++) {
arrR[i]=(complex*)fft(arr[i],m);
printf("%d ",i);
}
arrR=(complex**)transpose(arrR,n,m);
malloc(0);
for(i=0;i<m;i++)
arrR[i]=(complex*)fft(arrR[i],n);
arrR=transpose(arrR,n,m);
r=(complex***)&arrR;
return (complex**)*r;
}
complex** ifft_2d(complex** arr, int n, int m) {
complex **arrR, ***r, *temp;
int i, j;
arrR = (complex**)malloc(sizeof(complex*));
for(i=0;i<n;i++)
arrR[i]=(complex*)ifft(arr[i],m);
arrR=(complex**)transpose(arrR,n,m);
malloc(0);
for(i=0;i<m;i++)
arrR[i]=(complex*)ifft(arrR[i],n);
arrR=transpose(arrR,n,m);
r=(complex***)&arrR;
return (complex**)*r;
}
unsigned int** zoom_img(unsigned int **img, int col, int row, int r_col, int r_row) {
int i, j;
complex **mat=(complex**)malloc(sizeof(complex*)*col), **re;
complex **new_re=(complex**)malloc(sizeof(complex*)*(col+2*r_col)), **u;
unsigned int **result=(unsigned int**)malloc(sizeof(unsigned int*)*(col + 2*r_col)), ***z;
for(i=0;i<col;i++)
mat[i]=(complex*)malloc(sizeof(complex)*row);
for (i=0;i<col;i++) {
for (j=0;j<row;j++) {
mat[i][j].real = (float)pow(-1, i+j)*(float)img[i][j];
mat[i][j].im=0;
}
}
re = (complex**)fft_2d(mat, col, row);
for(i=0;i<(col+2*r_col);i++)
new_re[i]=(complex*)malloc(sizeof(complex)*(row+2*r_row));
for(i=0;i<(col+2*r_col);i++) {
for(j=0;j<(row+2*r_row);j++) {
if(i<r_col || i>r_col+col-1 || j<r_row || j>r_row+row-1) {
new_re[i][j].real = 0;
new_re[i][j].im = 0;
}
else
new_re[i][j]=re[i-r_col][j-r_row];
}
}
u = (complex**)ifft_2d(new_re, col+2*r_col, row + 2*r_row);
for(i=0;i<(col+2*r_col);i++) {
result[i]=(unsigned int*)malloc(sizeof(unsigned int)*(row+2*r_row));
for(j=0;j<(row+2*r_row);j++) {
result[i][j] = (unsigned int)u[i][j].real;
}
}
z=&result;
return *z;
}
int main() {
unsigned int i, j, **arr=(unsigned int**)malloc(sizeof(unsigned int*)*2), **result;
for(i=0;i<2;i++) {
arr[i]=(unsigned int*)malloc(sizeof(unsigned int)*2);
for(j=0;j<2;j++) {
arr[i][j] = i+j +1;
}
}
result = zoom_img(arr,2,2,2,2);
return 0;
}/*
int main() {
complex **arr, **result, **re;
arr=(complex**)malloc(sizeof(complex*)*4);
for (int i = 0; i < 4; i++) {
arr[i]=(complex*)malloc(sizeof(complex)*4);
for (int j = 0; j < 4; j++) {
arr[i][j].real = i*j+1.2;
arr[i][j].im=0;
}
}
result = (complex**)fft_2d(arr,4,4);
//malloc(0);
re = (complex**)ifft_2d(result,4,4);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
printf("(%2f) ", arr[i][j].real);
printComplexS(result[i][j]);
printf(" (%2f) ",re[i][j].real);
}
printf("\n");
}
return 0;
}*/
The code has several issues.
complex** ifft_2d(complex** arr, int n, int m) {
complex **arrR, ***r;
int i;
And then you are allocating too little:
arrR = (complex**)malloc(sizeof(complex*));
The above line should be malloc(sizeof(complex*) * n). Without the *n the next line causes undefined behavior (buffer overflow):
for(i=0;i<n;i++)
arrR[i]=(complex*)ifft(arr[i],m);
Then there is this strange line, why is it for?
malloc(0);
Then the ending of the function is weird (Why not simply return arrR?):
r=(complex***)&arrR;
return (complex**)*r;
Next, the recursive code (_ifft and _fft) assumes that size is a power of two, otherwise it gets into infinite recursion. You should validate the input. At least assert that:
assert(n >= 2);
assert(((n-1) & n ) == 0); // for positive n, assert that it is a power of 2
With this line you can see that zoom_img violates this assumption in the line:
u = (complex**)ifft_2d(new_re, col+2*r_col, row + 2*r_row);
Note that in the uncommented main, col==2, row==2, r_col==2, r_row==2, which ends up with size == 6, which is not a power of 2.
A smaller issue is performance. The code overuses malloc instead of reusing the same block of memory, and peek into different areas of it. This is what the classical FFT does. Classical FFT also does not use recursion like that, but uses iterations instead.
I am doing a convolution of two integer signals with the help of FFT, but somehow I can't get it right. I am not sure if my implementation of FFT is correct. Especially the math part.
big edit:
I posted all the code now. My apologies for not starting with it. I was sure the error was only in FFT part, but there might be more problems I overlooked. I know the code is messy and not clean. Everything is a bit fragmented and can be programmed in a simpler and cleaner way, but I was testing bit by bit. As for input it reads two signals from the command line. build up as a number indicating how big the signal is and the signal presented as an integer array e.q 2: [1,-1] and 10: [0,0,0,1,1,1,1,0,0,0]. It should then do a convolution on the signals by performing a FFT on both of them then do bit wise multiplication. With a inverse FFT on the resulting signal. Printing it again with the length and then the array consiting of integers. The printing itself is correct, but the values in the resulting array is not correct. I hope it is all a bit clearer now again my apologies and thank you for your help so far.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
double PI;
int *readSignal(int *len) { //reads the signal
int *x;
char c;
scanf("%d:", len);
x = calloc(*len, sizeof(int));
do c = getchar(); while (c != '[');
if (len > 0) {
scanf("%d", &x[0]);
for (int i=1; i < *len; i++) scanf(",%d", &x[i]);
}
do c = getchar(); while (c != ']');
return x;
}
void printSignal(int len, int *x) { //prints the signal
printf("%d: [", len);
if (len > 0) {
printf("%d", x[0]);
for (int i=1; i < len; i++)
printf(",%d", x[i]);
}
printf("]\n");
}
void *padSignal(int len, int lenSig, int *x) { //ensures that the signal is of size 2^n by padding it with 0's
int *padded;
padded = calloc(len, sizeof(int));
for (int i=0; i < lenSig; i++) {
padded[i] = x[i];
}
return padded;
}
void fft(double complex signal[], int length, int power) {
if (length == 1) {
return;
}
double complex *signalODD = calloc((length/2+1), sizeof(double complex));
double complex *signalEVEN = calloc((length/2+1), sizeof(double complex));
int index1 = 0;
int index2 = 0;
for(int i = 0; i < length; i++) {
if(i % 2 ==0) {
signalEVEN[index1] = signal[i];
index1++;
}
else {
signalODD[index2] = signal[i];
index2++;
}
}
fft(signalEVEN,length/2, power+1);
fft(signalODD,length/2, power+1);
for(int i = 0; i<length/2-1; i++) {
signal[i] = signalEVEN[i] + cexp((I*2*PI*i)/length)*signalODD[i];
signal[i+length/2] = signalEVEN[i]-cexp((I*2*PI*i)/length)*signalODD[i];
}
free(signalODD);
free(signalEVEN);
}
void ifft(double complex signal[], int length, int power) {
if (length == 1) {
return;
}
double complex *signalODD = calloc((length/2+1), sizeof(double complex));
double complex *signalEVEN = calloc((length/2+1), sizeof(double complex));
int index1 = 0;
int index2 = 0;
for(int i = 0; i < length; i++) {
if(i % 2 ==0) {
signalEVEN[index1] = signal[i];
index1++;
}
else {
signalODD[index2] = signal[i];
index2++;
}
}
fft(signalEVEN,length/2, power+1);
ifft(signalODD,length/2, power+1);
for(int i = 0; i<length/2-1; i++) {
signal[i] = signalEVEN[i] + cexp((I*-2*PI*i)/length)*signalODD[i];
signal[i+length/2] = signalEVEN[i]-cexp((I*-2*PI*i)/length)*signalODD[i];
}
free(signalODD);
free(signalEVEN);
}
int checkPowerofTwo(double len) { //checks for the closed power of 2
double x = 1;
while(len > pow(2,x)) {
x++;
}
return pow(2,x);
}
int main(int argc, char *argv[]) {
int lenH, *H;
int lenX, *X;
int *paddedX;
int *paddedH;
double length;
H=readSignal(&lenH); //reads in the signal H
X=readSignal(&lenX); //reads in signal X
length = lenH+lenX-1;
paddedH=padSignal((length),lenH,H); //pads the signal to the length
paddedX=padSignal((length),lenX,X); // pads the signal to the length
double complex *signalX = calloc(length, sizeof(double complex)); //creats a complex signal X and fills it with paddedX
for (int i = 0; i<length; i++) {
signalX[i] = paddedX[i];
}
double complex *signalH = calloc(length, sizeof(double complex)); // same for H
for (int i = 0; i<length; i++) {
signalH[i] = paddedH[i];
}
fft(signalX, length, 1); //performs the fast fourier transform on X
fft(signalH,length, 1); // performs the fast fourier transfom on H
double complex *signalY = calloc(length, sizeof(double complex)); //makes complex signal Y
for (int i = 0; i<length; i++) { //performs the convolution
signalY[i] = signalX[i]*signalH[i];
}
ifft(signalY, length,1);
int *output = calloc(length, sizeof(int)); //creates the final output signal
for (int i = 0; i<length; i++) {
output[i] = creal(signalY[i]);
}
printSignal(length,output);
free(signalX);
free(signalH);
free(signalY);
free(H);
free(X);
free(paddedH);
free(paddedX);
free(output);
return 0;
}
In:
if(i % 2 ==0 && i != 0)
Why do you exclude i == 0? Change that to if(i % 2 ==0) in both fft and ifft.
In both fft and ifft, the line:
for(int i = 0; i<lenght/2-1; i++) {
should be:
for(int i = 0; i<lenght/2; i++) {
In ifft, the recursion accidentally uses fft:
fft(signalEVEN,lenght/2, power+1);
fft(signalODD,lenght/2, power+1);
Change those to ifft.
The calloc calls do not need this much space:
calloc((lenght/2 + 1), sizeof(double complex));
That can be:
calloc((lenght/2), sizeof(double complex));
Also, the proper spelling of is “length”.
With those fixed, the fft and ifft routines appear to work for some superficial cases.
I'm trying to write Conway's game of life in C. This is what I have so far. I'm using pointers to refer to the arrays, which has never caused me problems before, but the function place_cell is causing a segfault.
Here's what I've tried so far:
- I tried making the grid with constants, 100 x 100, and 10 x 10. Modifying
values inside of those constant grids still gives me a segfault.
- I tried using constants for place_cell, still got a segfault.
int** make_grid(int x, int y) {
int** is = (int**)malloc(sizeof(int*) * y);
if(! is) {
fprintf(stderr, "make_grid: malloc failed");
exit(1);
}
int j;
for(j = 0; j < y; j++) {
is[j] = (int*)malloc(sizeof(int) * x);
if(!is[j]) {
fprintf(stderr, "make_grid: malloc failed");
exit(1);
}
}
return is;
}
/* takes two integers and places a cell at those coords */
void place_cell(int** is, int sidex, int sidey, int x, int y) {
if(x >= sidex || y >= sidey) {
fprintf(stderr, "place_cell: out of grid range\n");
exit(1);
}
is[y][x] = 1;
}
int check_surroundings(int** is, int sidex,
int sidey, int x, int y) {
int y_less = y - 1;
if(y == 0) {
y_less = sidey - 1;
}
int y_more = y + 1;
if(y == sidey - 1) {
y_more = 0;
}
int x_less = x - 1;
if(x == 0) {
x_less = sidex - 1;
}
int x_more = x + 1;
if(x == sidex - 1) {
x_more = 0;
}
int p = is[y_less][x_less] +
is[y_less][x] +
is[y_less][x_more] +
is[y][x_less] +
is[y][x_more] +
is[y_more][x_less] +
is[y_more][x_less] +
is[y_more][x_more];
return p;
}
void change_condition(int** is,
int sidex, int sidey, int x, int y) {
int* state = &is[y][x];
int surr = check_surroundings(is, sidex, sidey, x, y);
if(surr > 3) {
*state = 0;
} else if(surr == 3 || surr == 2) {
*state = 1;
} else {
*state = 0;
}
}
void print_grid(int** is, int sidex, int sidey) {
int i, j;
for(i = 0; i < sidey; i++) {
for(j = 0; j < sidex; j++) {
if(is[i][j] == 1) {
printf("*");
} else {
printf(" ");
}
}
printf("\n");
}
}
void new_generation(int** is, int sidex, int sidey) {
int i, j;
for(i = 0; i < sidey; i++) {
for(j = 0; j < sidex; j++) {
change_condition(is, sidex, sidey, j, i);
}
}
}
void play(int** is, int sidex, int sidey) {
int i = 0;
while(i < 100) {
new_generation(is, sidex, sidey);
print_grid(is, sidex, sidey);
i++;
}
}
here's my main:
int main(int argc, char* argv[]) {
int sidex = atoi(argv[0]);
int sidey = atoi(argv[1]);
int** is = make_grid(10, 10);
int i;
for(i = 2; i < argc; i += 2) {
place_cell(is, sidex, sidey,
atoi(argv[i]), atoi(argv[i + 1]));
}
return 0;
}
edit:
int** make_grid(int x, int y) {
int (*is)[x] = (int*)malloc(sizeof(int) * y * x);
if(! is) {
fprintf(stderr, "make_grid: malloc failed");
exit(1);
}
int j;
for(j = 0; j < y; j++) {
is[j] = (int*)malloc(sizeof(int) * x);
if(!is[j]) {
fprintf(stderr, "make_grid: malloc failed");
exit(1);
}
}
return is;
}
This isn't right at all but I can't put my finger on why. Can someone explain to me what to change like I'm five? (a five year-old who knows C, I guess)
I just copied your entire code and tried to run the program. The memory access violation (at least for me) is in this line:
int sidex = atoi(argv[0]);
int sidey = atoi(argv[1]); <-- memory access violation
The reason is (in my case at least) that I just ran the program with no arguments.
Now, even if I did provide the arguments on the command line the indexing is still off. The first argument argv[0] is the name of the executable, not the first argument after the name.
So, a few things to note for your code:
It is not guaranteed that there will be arguments. You should always check the argc to make sure you can index into argv
Those arguments are not guaranteed to be integer numbers either - you better check for that too, before you use them as your dimensions
Of course with the indexing shift you should adjust for your "array reading" code accordingly as well. But once you fix the indexing this should be an easy one for you
You are not declaring a two-dimensional array with that syntax, so the memory is not aligned the way you think, thus a segmentation fault. Declaring a pointer int** does not make it a 2-D array. (Surely you don't think int *** would get you a data cube ?).
Heap allocate a 2D array (not array of pointers)
One of the comments above gives the other problem, the zero parameter to a C program argv[0] is the name of the program, not the first parameter on the command line, that is argv[1].
I am trying to calculate a correlation measure for 18456 genes but the compiler (Dev C) exits after increasing macros GENE or INDEX to a value between 4000 and 5000 or bigger. For example it works well with:
# define GENE 4000
# define INDEX 3000
but not with:
#define GENE 5000
#define INDEX 100
The input file is a space delimited text file with 18456 rows and 57 columns.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <limits.h>
#define GENE 5000
#define N 57
#define INDEX 1000
int main (void) {
clock_t start, stop;
double t = 0.0;
int i, j, p, q, wp, wq;
double x;
double *S_matrix = (double *)malloc(INDEX * GENE * sizeof(double));
double sum_S, S_max;
double S[11] = {0};
double r = 0.0, xbar = 0.0, ybar = 0.0, sx = 0.0, sy = 0.0;
// read E matrix
FILE *fq;
double E[GENE][N] = {{0}};
if ((fq = fopen("E_disease.txt", "r")) == NULL )
{
printf("Error\n");
exit(EXIT_FAILURE);
}
fq = fopen("E_disease.txt","r");
printf("\n");
for (i=0;i<GENE;i++)
{
for(j=0;j<N;j++)
{
fscanf(fq,"%lf",&x);
E[i][j] = x;
}
}
printf("\n");
fclose(fq);
// calculate correlation
assert((start = clock())!=-1);
for(p=0; p < INDEX; p++)
{
for(q=0; q < GENE; q++)
{
for(i=0; i<11; i++)
{
/*compute xbar */
for(j = i; j < N; j++)
{
xbar += E[p][j];
}
xbar /= N;
/*compute ybar*/
for(j = i; j < N; j++)
{
ybar += E[q][j];
}
ybar /= N;
/* compute standard deviation of x*/
for(j = i; j < N; j++)
{
sx += (E[p][j] - xbar) * (E[p][j] - xbar);
}
sx = sqrt(sx);
/* compute standard deviation of y */
for(j = i; j < N; j++)
{
sy += (E[q][j] - ybar) * (E[q][j] - ybar);
}
sy = sqrt(sy);
/*compute r, the correlation coefficient between the two arrays */
for( j = i; j < N; j++ )
{
r += (((E[p][j] - xbar)/sx) * ((E[q][j] - ybar)/sy));
}
r /= (N);
if(r>0)
{
S[i] = r;
}
else if(r<=0)
{
S[i] = 0;
}
}
for(j=0, sum_S=0; j<11; j++)
{
sum_S += S[j];
}
for(j=0, S_max = 0; j<11; j++)
{
if(S[j] > S_max)
{
S_max = S[j];
}
}
S_matrix[p*GENE + q] = sum_S/(11*S_max);
}
}
FILE * fs;
fs = fopen ("s_matrix.txt", "w+");
for(wp=0; wp<INDEX; ++wp)
{
for(wq=0; wq<GENE; ++wq)
{
fprintf(fs, "%lf", S_matrix[wp*GENE + wq]);
fprintf(fs, "\t");
}
fprintf(fs, "\n");
printf("\n");
}
fclose(fs);
stop = clock();
t = (double) (stop-start)/CLOCKS_PER_SEC;
printf("Run time: %f\n", t);
//print results
//return (0);
getchar();
}
Let me simplify the code. When I ran the code below, a couple of times, it generally exited immediately. One time, it said that it could not find something like 0xff12345. Another time it printed out S_matrix[55] when I defined constants inside main (the rest of the code is same) like int GENE=100; but just one time. Is that mean a memory leak? It does not give an error message when I compile it but are defining matrices and assigning values to them true?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <time.h>
#include <limits.h>
#define GENE 100
#define N 57
#define INDEX 10
int main (void) {
//int GENE = 100;
//int N = 57;
//int INDEX = 10;
int i, j;
double x;
double *S_matrix = (double *)malloc(INDEX * GENE * sizeof(double));
double *E = (double*)malloc(GENE*N*sizeof(double));
// read E matrix
FILE *fq;
if ((fq = fopen("E_control.txt", "r")) == NULL )
{
printf("Error\n");
exit(EXIT_FAILURE);
}
fq = fopen("E_control.txt","r");
printf("\n");
for (i=0;i<GENE;i++)
{
for(j=0;j<N;j++)
{
fscanf(fq,"%lf",&x);
E[i*GENE+j] = x;
}
}
printf("\n");
fclose(fq);
for(i=0; i<INDEX; i++)
{
for(j=0; j<GENE; j++)
{
S_matrix[i*INDEX+j]=i*j;
}
}
printf("%f " , S_matrix[55]);
free(S_matrix);
S_matrix=NULL;
free(E);
E=NULL;
return(0);
getchar();
getchar();
}
You're attempting to reserve 2280000 bytes of stack space (actually more) in main() because of a overtly large fixed array declaration. Specifically, this line:
double E[GENE][N] = {{0}};
equates to
double E[5000][57] = {{0}};
At 8-bytes per double, thats highly likely to be blowing out your stack. Use dynamic allocation for that array instead. For example:
double (*E)[N] = malloc(5000*sizeof(*E));
And don't forget to free it when you're done.
Global fixed allocation will also work (i.e. declare it as a global outside the main() function block.
static double E[GENE][N];
int main()
{
... your code ...
}
Any method you choose has potential advantages and pitfalls, so plan accordingly.
I'm having problems understanding how to write code that solves the following problem: I have a structure containing a 2D-array. Then I have a recursive function that take a pointer to the structure as an argument and I want the recursive function to be able to manipulate the structure sent, not a local copy.
The struct is initialized in the function initStruct, where memory for the 2D-array is allocated. The recursive function builds up an array and at a specific point calls a function to insert it into the structure's array.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int** spBasis(int);
void mpBasis(int**, int, int, int, int, int, int, int*, struct mpBasis *, int, int);
void initMpBasis(struct mpBasis *, int, int);
void insertMpState(struct mpBasis *, int *);
struct mpBasis {
int** basis;
int size;
int capacity;
};
int main() {
int a, b, c, d;
char maxE[256];
char noParticles[256];
char P[256];
char M[256];
FILE *fp;
int **spStates;
struct mpBasis *mp;
int mpState[6] = {0, 0, 0, 0, 0, 0};
printf("Input max e for sp states, no of particles, parity (1 for odd and 0 for even) and magnetic projection: ");
gets(maxE);
gets(noParticles);
gets(P);
gets(M);
spStates = spBasis(atoi(maxE));
fp = fopen("spStates.txt", "a+");
fprintf(fp, "E\tj\tl\tm\n");
for (a = 0; a < 330; a++) {
fprintf(fp, "State %d: ", a+1);
for (b = 0; b < 4; b++) {
fprintf(fp, "%d\t", spStates[a][b]);
}
fprintf(fp, "\n");
}
mp = malloc(sizeof(struct mpBasis));
initMpBasis(mp, 5449, 6);
for (c = 0; c < 5449; c++) {
for (d = 0; d < 6; d++) {
fprintf(fp, "%d: %d\t", c, mp->basis[c][d]);
}
fprintf(fp, "\n");
}
printf("%p\n", (void*) mp);
printf("hello 3");
mpBasis(spStates, 0, atoi(maxE), 0, atoi(M), 0, atoi(P), mpState, mp, 0, 0);
fclose(fp);
return 0;
}
int** spBasis(int maxE) {
int c;
int i, j, k, l;
int q = 0;
int** spStates;
spStates = (int**)malloc(330 * sizeof(int *));
for (c = 0; c < 330; c++) {
spStates[c] = malloc(4 * sizeof(int));
}
for (i = 0; i <= maxE; i++) {
for (j = i % 2; j <= i; j += 2) {
for (k = -(2 * j + 1); k <= (2 * j + 1); k += 2) {
spStates[q][0] = i;
spStates[q][1] = j;
spStates[q][2] = 2 * j + 1;
spStates[q][3] = k;
q += 1;
}
for (l = -(2 * j - 1); l <= (2 * j - 1); l += 2) {
spStates[q][0] = i;
spStates[q][1] = j;
spStates[q][2] = 2 * j - 1;
spStates[q][3] = l;
q += 1;
}
}
}
return spStates;
}
void mpBasis(int** spStates, int e, int maxE, int m, int M, int l,
int P, int * mpState, struct mpBasis *mpB, int position, int lastSpState) {
int i;
for (i = lastSpState; i < 330; i++) {
if (e > maxE) {
break;
} else if (position == 5) {
if (m == M && l % 2 == P) {
insertMpState(mpB, mpState);
break;
}
} else {
// add spState to mpState and make the recursive call for the next position
mpState[position] = i;
mpBasis(spStates, e + spStates[i][0], maxE, m + spStates[i][3], M,
l + spStates[i][1], P, mpState, mpB, position+1, i);
}
}
}
void initMpBasis(struct mpBasis *a, int initialSize, int sizeY) {
int c;
a->basis = (int **)malloc(initialSize * sizeof(int*));
for (c = 0; c < initialSize; c++) {
a->basis[c] = (int *) malloc(sizeY * sizeof(int));
}
a->size = 0;
a->capacity = initialSize;
}
void insertMpState(struct mpBasis *a, int* mpState) {
/*if (a->size == a->capacity) {
a->size *= 2;
a->basis = (int **)realloc(a->basis, a->size * sizeof(int));
}*/
a->basis[a->size++] = mpState;
}
Added all the code.
The problem is that after the recursive function has been called, the "basis" array in structure mpBasis still only contains random values, i.e. the mpBasis function hasn't done anything with it. Am I passing the mp argument by value here?
Thanks for your help!
The first step is to compile with warnings enabled. Eg if you are using GCC you can use option -Wall -Wextra.
EDIT:
(previous listing of >20 errors removed)
Ok, since you are using Visual Studio, enable warnings like this:
Open the project's Property Pages dialog box.
Select C/C++.
On the General property page, modify the Warning Level to /W4