Exception thrown, Dynamic memory allocation in C - c

Hi I'm trying to do dynamic memory allocation of a large matrix in C but I'm running into the following error:
Exception thrown at 0x00007FF63A248571 in cdempd.exe: 0xC0000005: Access violation writing location 0x0000000000000000. occurred
sometimes it's Access violation writing location 0xFFFFFFFFB412E2A0.
double ndivx, ndivy, ndivz, nt, r, box, dx, totnode;
int main()
{
ndivx = 19.0;
ndivy = 19.0;
ndivz = 19.0;
int totnode = ndivx * ndivy * ndivz;
r = 0.005; //diameter of sphere
dx = 0.0025 / ndivx;
double dx = r / ndivx; // distance between points
int cols = 3;
int** coords;
coords = malloc(totnode * sizeof(int*));
for (int i = 0; i < totnode; i++) {
coords[i] = malloc(cols * sizeof(int));
}
//int* coord = (int*)malloc(totnode * cols * sizeof(int));
// int offset = i * cols + j;
// now mat[offset] corresponds to m(i, j)
//create a cube of equidistant points
int numm = 0;
for (int i = 1; i <= ndivx; i++)
{
for (int j = 1; j <= ndivy; j++)
{
for (int k = 1; k <= ndivz; k++)
{
coords[numm][0] = -1.0 / 2.0 * (r)+(dx / 2.0) + (i - 1.0) * dx;
coords[numm][1] = -1.0 / 2.0 * (r)+(dx / 2.0) + (j - 1.0) * dx;
coords[numm][2] = -1.0 / 2.0 * (r)+(dx / 2.0) + (k - 1.0) * dx;
numm = numm + 1;
}
}
}
}
pd.r is a double 0.005, dx is a double about 0.00026315, totnode is 6859.
I've tried two methods, the one that is there and the one commented out with //. Both give me the same error. I'm using visual studio 2019. I'm not so familiar with c and visual studio so forgive me if the question is silly. Any help would be appreciated thank you.

Aside from some of the other errors [after correction], all values of coords are set to zero. This is because coords is a pointer to int and not (e.g.) double and your equation uses -1.0 / ... which will always produce a fraction.
Also, as David pointed out, you're indexing from 1 [vs. 0] in the for loops. This could cause access violations/segfaults.
I've changed the for loops to start from 0. And, I've adjusted the equation accordingly (using a macro).
You were defining some things like index variables or size variables as double instead of int (e.g.) ndivx
Also, I introduced a typedef for the coordinate values.
Here's some cleaned up code that may help get you further:
#include <stdio.h>
#include <stdlib.h>
#if 0
double ndivx, ndivy, ndivz, nt, r, box, dx, totnode;
#endif
#if 0
typedef int coord_t;
#else
typedef double coord_t;
#endif
#define SETCOORD(_xidx,_var) \
do { \
coords[numm][_xidx] = -1.0 / 2.0 * r + (dx / 2.0) + (_var * dx); \
printf("coords[%d][%d]=%g\n",numm,_xidx,(double) coords[numm][_xidx]); \
} while (0)
int
main(void)
{
#if 1
int ndivx;
int ndivy;
int ndivz;
double r;
double dx;
#endif
ndivx = 19;
ndivy = 19;
ndivz = 19;
int totnode = ndivx * ndivy * ndivz;
r = 0.005; // diameter of sphere
dx = 0.0025 / ndivx;
#if 0
double dx = r / ndivx; // distance between points
#else
dx = r / ndivx; // distance between points
#endif
int cols = 3;
#if 0
int **coords;
#else
coord_t **coords;
#endif
coords = malloc(totnode * sizeof(coord_t *));
for (int i = 0; i < totnode; i++) {
coords[i] = malloc(cols * sizeof(coord_t));
}
// int* coord = (int*)malloc(totnode * cols * sizeof(int));
// int offset = i * cols + j;
// now mat[offset] corresponds to m(i, j)
// create a cube of equidistant points
int numm = 0;
for (int i = 0; i < ndivx; i++) {
for (int j = 0; j < ndivy; j++) {
for (int k = 0; k < ndivz; k++) {
SETCOORD(0,i);
SETCOORD(1,j);
SETCOORD(2,k);
numm = numm + 1;
}
}
}
return 0;
}

Related

Miscalculation of Lagrange interpolation formula for higher degree

I am approximating Runge’s function using Lagrange’s interpolation formula for 50 interpolation points. I have written the following program to do this, but I am getting the wrong value for x= -0.992008. That wrong value is 4817543.091313, but it should be 5197172.55933613. I have got this value from the following link: Link The code used are as follows:
#include <stdio.h>
#include <math.h>
double
runge(double x)
{
return (1 / (1 + (25 * x * x)));
}
double
ab(double x)
{
if (x < 0)
return -1 * x;
return x;
}
double
lag_func(double x, double *y_i, double *x_i, int n)
{
double ex = 0.0;
for (int i = 0; i <= n; i++) {
double numer = 1.0,
denom = 1.0,
prod = 1.0;
for (int j = 0; j <= n; j++) {
if (i != j) {
numer = (x - x_i[j]);
denom = (x_i[i] - x_i[j]);
prod *= numer / denom;
}
}
ex += (prod) * y_i[i];
}
return ex;
}
int
main()
{
int n;
scanf("%d", &n);
double y_i[n + 1],
x_i[n + 1];
for (int i = 0; i < n + 1; i++) {
x_i[i] = ((2 * (double) i) / (double) n) - 1;
y_i[i] = runge(x_i[i]);
}
printf("%lf\n", lag_func(-0.992008, y_i, x_i, n));
return 0;
}
The web site is rounding its Runge coefficients to six digits. Given the magnitudes of the terms involved, up to 3.9978•1011, this introduces multiple errors up to around 2•105.
This can be seen by inserting y_i[i] = round(y_i[i] * 1e6) / 1e6; after y_i[i] = runge(x_i[i]);. Then the output of the program is 5197172.558199, matching the web site’s inaccurate result.
The web site is wrong; the result of the code in the question is better.

Writing a C array to 3D volume in vtk format using array strides and grid spacing

Suppose I have an array of floating points (malloced) and this array represents a 3d volume of nx * ny * nz with strides in the respective directions as sx = 1, sy = nx and sz = nx * ny. The grid spacing is say some constant dx. How can I write this data into a vtk file (I suppose vtkImage should be the format I should look at) for visualization in Paraview?
A minimal example for the data arrangement as described above is as follows:
#include <math.h>
#include <stdio.h>
int main()
{
/* array dim */
int nx = 512;
int ny = 512;
int nz = 512;
long int nt = nx * ny * nz; /* total values */
/* strides */
int sx = 1;
int sy = nx;
int sz = nx * ny;
/* grid spacing (can be different as well, in which case rectillinear grid should be needed) */
dx = 40.;
dy = 40.;
dz = 40.;
/* allocation */
float* data = malloc(nx * ny * nz * sizeof(float));
/* fill up values */
for (int k = 0; k < nz; k++)
for (int j = 0; j < ny; j++)
for (int i = 0; i < nx; i++) {
data[sx * i + sy * j + sz * k ] = 5.0; // constant but could be a mathematical function
}
/* how to write this array to a vtk file ? */
return 0;
}

How can I improve locality of reads and writes in the following code?

I'm working on the following image convolution code:
typedef struct fmatrix{
int rows;
int cols;
float** array;
} fmatrix;
typedef struct image{
unsigned char* data;
int w;
int h;
int c;
} image;
typedef struct kernel{
fmatrix* psf;
int divisor;
} kernel;
void convolve_sq(image* src, image* dst, kernel* psf, int pixel){
int size = psf->psf->rows * psf->psf->cols;
float tmp[size];
int n, m; //for psf
int x, y, x0, y0, cur; //for image
y0 = pixel / (src->w * src->c);
x0 = (pixel / src->c) % src->w;
for (n = 0; n < psf->psf->rows; ++n){
for (m = 0; m < psf->psf->cols; ++m){
y = n - (psf->psf->rows / 2);
x = m - (psf->psf->cols / 2);
if ((y + y0) < 0 || (y + y0) >= src->h || (x + x0) < 0 || (x + x0) >= src->w){
tmp[n*psf->psf->rows+m] = 255 * psf->psf->array[n][m];
}
else{
cur = (pixel + y * src->w * src->c + x * src->c);
tmp[n*psf->psf->rows+m] = src->data[cur] * psf->psf->array[n][m]; //misses on read
}
}
}
m = 0;
for (n = 0; n < size; ++n){
m += (int) tmp[n];
}
m /= psf->divisor;
if (m < 0) m = 0;
if (m > 255) m = 255;
dst->data[pixel] = m; //misses on write
}
void convolve_image(image* src, image* dst, kernel* psf){
int i, j, k;
for (i = 0; i < src->h; ++i){
for (j = 0; j < src->w; ++j){
for (k = 0; k < src->c; ++k){
convolve_sq(src, dst, psf, (i * src->w * src->c + j * src->c + k) );
}
}
}
}
Running cachegrind, I've determined two places where there are a substantial number of cache misses, which I've annotated in the code above. For the line marked "misses on read", there were 97,205 D1mr and 97,201 DLmr. For the line marked "misses on write", there were 97,201 D1mw and DLmw. These lines read and write directly to/from the image respectively.
How can I make this code more efficient, in terms of avoiding cache misses?

Math Equation not outputting result I want

The purpose of the program is to calculate the volume at each depth. The inputs are the radius and length and in this test case they are 2.1 and 5.6 respectively. I keep getting 0, 1, 2, 3, and 4 for my volume but that's not the right volume, the depth/height is correct so perhaps someone can shed light on whats wrong with my equation below?
This is the function that calculates the volume
int getVolume(double arrplotptr[][col], double *arr2ptr, char *nameptr)
{
double vol, h, diam, ctr, rad, len, x;
int i, j;
rad = arr2ptr[radius];
len = arr2ptr[length];
diam = (rad * 2);
ctr = diam / 100;
h = 0;
for (j = 0; j < 100; j++) {
h = h + ctr;
arrplotptr[0][j] = h;
}
h = 0;
for (i = 0; i < 100; i++) {
h = h + ctr;
x = (rad - h) / rad;
vol = ((rad * rad) * acos(x) - (rad - h) * (sqrt((2 * rad * h) - (h * h)))) * len;
arrplotptr[1][i] = vol;
}
}
I see several issues in your code:
Why do you use ctr = diam / 100; instead of ctr = rad / 100;?
You do not return a value from getVolume, if the caller function relies on the return value, you invoke undefined behavior.
You store the volume of each slice but do not compute the total volume. You did not post the code that does that, maybe there are problems there too.
As written by chqrlie, I think you should change
ctr = diam / 100;
with
ctr = rad / 100;
And, as written by EOF, the function is defined as "int" but returns no value; You should redefine it as "void" or return an integer value.
I add that it doesn't seem necessary to double loop: in each iteration you can calculate "h", "x", "vol" and save the two values of "arrplotptr".
I propose to simplify the function as follows
void getVolume (double arrplotptr[][col], double arr2ptr[])
{
double const rad = arr2ptr[radius];
double const len = arr2ptr[length];
double const ctr = rad / 100;
int i;
double h;
for ( i = 0, h = ctr ; i < 100 ; ++i, h+=ctr )
{
arrplotptr[0][i] = h;
arrplotptr[1][i] = ((rad * rad) * acos((rad - h) / rad)
- (rad - h) * (sqrt((2 * rad * h) - (h * h)))) * len;
}
}

Sobel Operator C - Edge detection gone wrong

I ve been trying hard to calculate the gradient (and dips) of a binary image in C using the Sobel operator. I ve already checked the operators several times and went through tons of internet sites. Nevertheless, I have to admit that I have no experience with image processing and I am quite a rookie in C coding. I dont get any error messages, but the result does not show the desired gradients on the edges.
Somehow the gradient in the x-direction is not calculated - but why?
Thanks for the help!
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
FILE *infile, *outfile;
int main(int argc, char *argv[])
{
int nx,nz,k,i,nu;
int j,m,l;
int km, kp, im, ip, kpp, ipp;
float Gx, Gz, G, Gmax, Gmin;
float T;
float **dip;
float pi;
float *tmp;
float *bufz;
float **temp1;
char *velfile_in = "vel";//"vel_315_273";
char *velfile_out = "dip";
void *alloc1 (size_t n1, size_t size);
void **alloc2(size_t n1, size_t n2, size_t size);
void ***alloc3(size_t n1, size_t n2, size_t n3, size_t size);
pi = 4. * atan(1.);
// Initiate constants
T = atof(argv[1]);
nx = atoi(argv[2]);
nz = atoi(argv[3]);
Gmax = 0.;
Gmin = 10e8;
// border handling (cyclic)
km = (k+nz-1) % nz;
kp = (k+1) % nz;
kpp = (k+2) % nz;
im = (i+nx-1) % nx;
ip = (i+1) % nx;
ipp = (i+2) % nx;
// allocate 1D, 2D and 3D arrays
tmp = (float *)alloc1(nz,sizeof(float));
bufz = (float *)alloc1(nz,sizeof(float));
temp1 = (float **)alloc2(nx,nz,sizeof(float));
dip = (float **)alloc2(nx,nz,sizeof(float));
//READ FILE
//***********************************************************
infile = fopen(velfile_in, "r");
if (infile == NULL) err("Error: could not open file.");
for (i=0; i<nx; i++) {
nu = fread(tmp,sizeof(float),nz,infile);
for (k=0; k<nz; k++) {
temp1[k][i] = tmp[k];
}
}
fclose(infile);
// APPLY SOBEL****************************************
for (i = 0; i < nx; i++)
{
for (k = 0; k < nz; k++)
{
Gx = (temp1[km][im] - temp1[km][ip] + 2 * temp1[k][im] - 2 * temp1[k][ip] + temp1[kp][im] - temp1[kp][ip]);
Gz = (temp1[km][im] - temp1[kp][im] + 2 * temp1[km][i] - 2 * temp1[kp][i] + temp1[km][ip] - temp1[kp][ip]);
G = sqrtf(Gx * Gx + Gz * Gz);
Gmax = (Gmax > G ? Gmax : G);
Gmin = (Gmin < G ? Gmin : G);
dip[k][i] = abs(atan(Gz/Gx) * 180. / pi);
printf("(%d,%d)\tGx:%5.3f\tGz%5.3f\tG%5.3f\n",i,k,Gx,Gz,G);
}
}
printf("Gmax:%5.3f\tGmin:%5.3f\n",Gmax,Gmin);
// write file ********************************************************
outfile = fopen(velfile_out,"w");
for (i=0; i<nx; i++) {
for (k=0; k<nz; k++) bufz[k] = dip[k][i];
fwrite(bufz,sizeof(float),nz,outfile);
}
fclose(outfile);
return 0;
}
The obvious problem is that your convolution kernel isn't moving - the array indices are all separate variables and need updating to stay in sync with i and j. Moving the assignments inside the loops should fix that:
...
for (i = 0; i < nx; i++)
{
im = (i+nx-1) % nx;
ip = (i+1) % nx;
ipp = (i+2) % nx;
for (k = 0; k < nz; k++)
{
km = (k+nz-1) % nz;
kp = (k+1) % nz;
kpp = (k+2) % nz;
...

Resources