I am constantly facing a fatal error when calling a C function in R and I suspect it may be because of the way I have used "realloc" routine for variable n_k in the gCRSF_gibbs function. Can somebody tell me if the reallocation of memory to n_k is correct or not?
void gCRSF_gibbs(double *z, double **n_k, double *SampleDex,
double *r, double *a, double *p,
int *Ksize, int *WordNum) {
int i, j, k;
double mass;
double *prob_cumsum;
double cum_sum, probrnd;
prob_cumsum = (double *) calloc(Ksize[0],sizeof(double));
mass = r[0]*pow(p[0],-a[0]);
for (i=0;i<WordNum[0];i++){
j = (int) SampleDex[i] -1;
k = (int) z[j] -1;
if(z[j]>0){
(*n_k)[k]--;
}
for (cum_sum=0, k=0; k<Ksize[0]; k++) {
cum_sum += (*n_k)[k]-a[0];
prob_cumsum[k] = cum_sum;
}
if ( ((double) rand() / RAND_MAX * (cum_sum + mass) < cum_sum)){
probrnd = (double)rand()/(double)RAND_MAX*cum_sum;
k = BinarySearch(probrnd, prob_cumsum, Ksize[0]);
}
else{
for (k=0; k<Ksize[0]; k++){
if ((int) (*n_k)[k]==0){
break;
}
}
if (k==Ksize[0]){
Ksize[0]++;
realloc(*n_k,sizeof(**n_k)*Ksize[0]);
(*n_k)[Ksize[0]-1]=0;
prob_cumsum = realloc(prob_cumsum,sizeof(*prob_cumsum)*Ksize[0]);
}
}
z[j] = k+1;
(*n_k)[k]++;
}
free(prob_cumsum);}
And this is how it is called in R:
gCRSF_gibbs <- function(z, n_k, sampleDex, r, a, p){
out <- .C("gCRSF_gibbs", z=as.double(z), n_k=as.double(n_k),
SampleDex=as.double(sampleDex), r=as.double(r), a=as.double(a),
p=as.double(p), Ksize=as.integer(length(n_k)),
WordNum=as.integer(length(sampleDex)))
out}
You're using realloc wrong. It should be:
*n_k = realloc(*n_k,sizeof(**n_k)*Ksize[0]);
You always want to use realloc like p = realloc(p, size). Otherwise, if the buffer gets moved by realloc, *n_k will be pointing to a freed pointer.
Related
So I am currently writing a function that can output data to an array ready for export to text. Function works fine when collecting variables but an getting the "Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)" error within Xcode and don't know how to debug this. I have tried using calloc to assign memory to the array and using address locations but am still getting similar error messages and using address locations just don't work.
Has anyone got any suggestions for how I can solve this? The error code is showing itself on the first line of the for loop and this function is running as part of a larger function.
void LamVelProf(double dP, double L, double d, double mu)
{
double *r = malloc(sizeof(r)); //Point radius from centreline
double *R = malloc(sizeof(R)); //Absolute pipe radius
double *vx = malloc(sizeof(vx));
double *gvx = malloc(sizeof(gvx));
double *offset = malloc(sizeof(offset));
double **profile[7500][4];
**profile = calloc((7500*4), sizeof(double));
//double **profile = calloc((7500*4), sizeof(double));
int *i = malloc(sizeof(i));
*R = d/2; //Setting the boundary condition
*offset = 0.001;
*i = 0;
for(*r = 0; *r < (*R + (*offset/2)); *r = (*r)+(*offset))
{
**profile[*i][0] = *r;
LamVelProCalc(dP, L, d, mu, *r, vx);
**profile[*i][1] = *vx;
LamGenProCalc(*r, d, gvx);
**profile[*i][2] = *gvx;//Results from general profile
**profile[*i][3] = *i+1;
++*i; //Increasing count by 1
}
printf("%i rows generated\n", *i);
free(r);
free(R);
free(offset);
int *row = malloc(sizeof(row));
int *col = malloc(sizeof(col));
for(*row = 0; *row < *i + 1; *row = *row + 1)
{
for(*col = 0; *col < 4; *col = *col + 1)
{
printf("%f", **profile[*row][*col]);
if(*col == 3)
{
printf("\n");
}else{
printf("\t");
}
}
}
}
I've had to aggressively de-pointerize this code to bring it back into the realm of understandability, and the end result is this:
void LamVelProf(double dP, double L, double d, double mu)
{
double R = d/2;
double offset = 0.001;
double profile[7500][4];
int i = 0;
for (double r = 0; r < (R + (offset/2)); r += offset) {
double vx = 0.0; // Initialize appropriately
double gvx = 0.0;
profile[i][0] = r;
// No idea what this does, or why the return value is ignored
LamVelProCalc(dP, L, d, mu, r, vx);
profile[i][1] = vx;
// No idea what this does, or why the return value is ignored
LamGenProCalc(r, d, gvx);
profile[i][2] = gvx;//Results from general profile
profile[i][3] = i+1;
++i; //Increasing count by 1
}
printf("%i rows generated\n", i);
for(int row = 0; row < i + 1; ++row)
{
for(int col = 0; col < 4; ++col)
{
printf("%f", profile[row][col]);
if (col == 3) {
printf("\n");
} else {
printf("\t");
}
}
}
}
As you can see there's two function calls buried in there that should probably have pointer arguments, my guess is vx and gvx are intended to be manipulated by that function. In C it is common to use use pointers to manipulate external variables, so a pointer argument almost always means "array" or "mutable argument" depending on context.
In other words I'd expect to see:
LamVelProCalc(dP, L, d, mu, r, &vx);
Or even better:
double vx = LamVelProCalc(dP, L, d, mu, r);
Where that value is explicitly returned instead.
This should compile and run without crashing now, though note the above mentioned issues.
When it comes to compiler suggestions to fix a problem, remember to take them all under advisement. At the end of the day you're the programmer, not the compiler, and not every educated guess it makes will be a valid interpretation of the problem at hand. If you unwaveringly follow the compiler's advice it may lead you down really, really strange paths, as perhaps has happened here.
As a note, having variables r and R is borderline programmer abuse. Please don't do this.
Another thing to keep in mind is your rather arbitrary use of 7500 here. Is that just a wild guess as to how many entries you'll need? It's almost always better to compute that, you know how the for loop will run in advance so you can do the math, and allocate accordingly.
If it is a limit you've arrived at through some other method it's worth using a #define to indicate as such, like:
#define MAX_PROFILE_ENTRIES 7500
Where it's now clear what the meaning behind that number is.
So after a lot of head scratching and realising I didn't need malloc because my array would definitely never reach the 125000 elements. Thanks to #tadman for helping with that. Here's the final program which is designed to be called from a menu function:
//
// 02g1LamVelPro .c
// Process Model (MacOS Version)
//
// Created by --- on 30/06/2020.
// Copyright © 2020 ---. All rights reserved.
//
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define maxstrlen 128
//Declaring global variables and allocating memory
//Function Output
double profile; //Array of doubles
//Calculation Variables
double dP;
double L;
double d;
double mu;
double r;
//Miscellaneous Variables
void LamVelProVar(double *dP, double *L, double *d, double *mu)
{
//Declaring input variables
char pres[maxstrlen];
char len[maxstrlen];
char dia[maxstrlen];
char visc[maxstrlen];
printf("Fluid pressure loss (Pa) = ");
*dP = atof(fgets(pres, sizeof(pres), stdin));
printf("Pipe length (m) = ");
*L = atof(fgets(len, sizeof(len), stdin));
printf("Pipe diameter (mm) = ");
*d = atof(fgets(dia, sizeof(dia), stdin));
*d = (*d)*0.001;
printf("Fluid viscosity (cP) = ");
*mu = atof(fgets(visc, sizeof(visc), stdin));
*mu = (*mu)*0.001;
fflush(stdout);
}
double LamVelCalc(double dP, double L, double d, double mu, double r, double *v_x)
{
//Calculation of the theoretical velocity profile with the flow possessing laminar characteristics
double frac1;
double frac2;
double frac3;
frac1 = (dP/L);
frac2 = pow(d,2);
frac2 = (frac2)/(16*mu);
frac3 = 2*r;
frac3 = (frac3)/d;
frac3 = pow(frac3, 2);
frac3 = 1 - (frac3);
*v_x = frac1 * frac2;
*v_x = (*v_x) * frac3;
return *v_x;
}
double LamGenCalc(double r, double d, double *func)
{
//Calculation of the general velocity profile with the flow possessing laminar characteristics
*func = 2*r;
*func = (*func)/d;
*func = pow(*func, 2);
*func = 1 - (*func);
return *func; //Returns v/v_max
}
double **LamVelProfCalc(double dP, double L, double d, double mu)
{
char display[maxstrlen];
double v_x = 0;
double offset = 0.0001;
//Calculating number of rows for the profile results matrix
double prad = d/2;
int whildisp = 1;
int rows = ((prad)/ (offset)) + 1;
printf("%i rows required\n", rows);
double profile[rows][3];
int i = 0;
for(double r = 0.0; r < (prad + (offset/2)); r += offset)
{
profile[i][0] = r; //Displaying point radius
profile[i][1] = LamVelCalc(dP, L, d, mu, r, &v_x); //Calculating point velocity
profile[i][2] = LamGenCalc(r, d, &v_x); //Calculating
//profile[i][3] = i + 1;
++i;
}
printf("%i rows successfully generated\n\n", i);
while(whildisp == 1)
{
printf("Do you want to display the generated data? ");
fgets(display, sizeof(display), stdin);
switch(display[0])
{
case '1':
case 'Y':
case 'y':
printf("Displaying data\n");
printf("Inputted variables:\n");
printf("dP =\t%.3f\tPa\n", dP);
printf("L =\t%.3f\tm\n", L);
printf("d =\t%.1f\tmm\n", d*1000);
printf("mu =\t%.3f\tPa.s\n", mu);
printf("v_max =\t%.3f\tm/s\n\n", LamVelCalc(dP, L, d, mu, 0, &v_x));
printf("r (m)\tv_x (m/s)\tv/v_max\n");
int row = 0;
int col = 0;
for(row = 0; row < i; ++row)
{
for(col = 0; col < 3; ++col)
{
printf("%.5f", profile[row][col]);
if(col == 2)
{
printf("\n");
}else{
printf("\t");
}
}
}
whildisp = 0;
break;
case '0':
case 'N':
case 'n':
whildisp = 0;
default:
printf("Input not recognised.\n");
break;
}
}
return profile;
}
void LamVelPro()
{
//Main Function
char ContCond[maxstrlen];
int whilmain = 1;
printf("Laminar flow velocity profile\n");
while(whilmain == 1)
{
//Variable declaration
double dP;
double L;
double d;
double mu;
double r;
//Data collection
LamVelProVar(&dP, &L, &d, &mu);
//Data manipulation
LamVelProfCalc(dP, L, d, mu);
//Ask for file write (Remember while loop)
//...
//Continue function
int whilcont = 1;
while(whilcont == 1)
{
printf("Do you want to continue? ");
fgets(ContCond, sizeof(ContCond), stdin);
switch(ContCond[0])
{
case '1':
case 'T':
case 'Y':
case 't':
case 'y':
whilcont = 0;
break;
case '0':
case 'F':
case 'N':
case 'f':
case 'n':
whilcont = 0;
whilmain = 0;
break;
default:
printf("Input not recognised\n");
break;
}
}
}
fflush(stdout);
}
I am extremely new to C and managed to compile this program, but the exe stops working upon running. I'm really not sure what's wrong.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define TINY 1.0e-20 // A small number.
void ludcmp(float a[3][3], int n, int *indx, float *d);
void lubksb(float a[3][3], int n, int *indx, float b[]) ;
int main(){
int i,n,*indx;
float *b,d;
float a[3][3] = {
{ 1.0, 2.0, 5.0},
{-1.0, 2.0, 3.0},
{ 6.0, 0.0, 1.0}
};
ludcmp(a,n,indx,&d);
lubksb(a,n,indx,b);
for(i = 1; i = 3; i++) {
printf("%.2f",b[i]);
}
getchar();
return 0;
}
For those who were asking, the 2 functions ludcmp and lubksg are below. I got them from the numerical recipes textbook, but edited some lines to remove exclusive routines which I do not have. Specifically, they are the lines with malloc, printf, and free.
The original code came with all the loops starting with 1, which is why I also started my loop with 1. I have since changed all the loops to start from 0 instead, hopefully without introducing any new errors.
You can see the original code here:
https://github.com/saulwiggin/Numerical-Recipies-in-C/tree/master/Chapter2.Solution-of-Linear-Equations
Here is ludcmp:
void ludcmp(float a[3][3], int n, int *indx, float *d)
{
int i, imax, j, k;
float big, dum, sum, temp;
float *vv; // vv stores the implicit scaling of each row.
vv = (float *) malloc(n * sizeof(float));
*d=1.0;
for (i=0;i<n;i++) {
big=0.0;
for (j=0;j<n;j++)
if ((temp=fabs(a[i][j])) > big) big=temp;
if (big == 0.0)
{
printf("Singular matrix in routine ludcmp");
//free(vv);
}
// No nonzero largest element.
vv[i] = 1.0 / big; // Save the scaling.
}
// This is the loop over columns of Crout's method.
for (j=0;j<n;j++) {
for (i=0;i<j;i++) {
sum=a[i][j];
for (k=0;k<i;k++) sum -= a[i][k]*a[k][j];
a[i][j]=sum;
}
// Initialize for the search for largest pivot element.
big=0.0;
for (i=j;i<=n;i++) {
sum=a[i][j];
for (k=0;k<j;k++)
sum -= a[i][k]*a[k][j];
a[i][j]=sum;
if ( (dum=vv[i]*fabs(sum)) >= big) {
big=dum;
imax=i;
}
}
if (j != imax) {
for (k=0;k<n;k++) {
dum=a[imax][k];
a[imax][k]=a[j][k];
a[j][k]=dum;
}
*d = -(*d);
vv[imax]=vv[j];
}
indx[j]=imax;
if (a[j][j] == 0.0) a[j][j]=TINY;
if (j != n) {
dum=1.0/(a[j][j]);
for (i=j+1;i<n;i++) a[i][j] *= dum;
}
} // Go back for the next column in the reduction.
free(vv);
}
And lubksb:
void lubksb(float a[3][3],int n,int *indx,float b[])
{
int i,ii=0,ip,j;
float sum;
for (i=1;i<=n;i++) {
ip=indx[i];
sum=b[ip];
b[ip]=b[i];
if (ii)
for (j=ii;j<=i-1;j++) sum -= a[i][j]*b[j];
else if (sum) ii=i;
b[i]=sum;
}
for (i=n;i>=1;i--) {
sum=b[i];
for (j=i+1;j<=n;j++) sum -= a[i][j]*b[j];
b[i]=sum/a[i][i];
}
}
This is a Two Dimensional Array and you are looping as it was just one. You should do something like:
for (int i = 0; i < 3; ++i) {
for(int j = 0; j < 3; ++j) {
printf("%d %d: ", i+1, j+1);
}
}
Is bad practice to define the size of the array explicit. Try to use a constant.
And as said in the comments by #Marged:
In C arrays starts in 0
b is never assigned to anything valid when it's declared:
float *b,d;
At best, it's NULL or pointing to an invalid memory address:
I don't know what the lubksb function does:
lubksb(a,n,indx,b);
But b is clearly an invalid parameter since you never assign to it before calling this function.
And with this statement:
for(i = 1; i = 3; i++) {
printf("%.2f",b[i]);
}
As others have pointed out, array indices start at zero. But there's no evidence that b has a length of three anyway.
I am trying to build and run the following code on code blocks, but it crashes and returns the (0xC0000005) error. I mainly suspect the usage of realloc for pointer n_k in gCRSF_gibbs function, however I am not sure how to track the source of crash. This is not my original code and I am also a noob in C. Any kind of help is appreciated.
#include <stdio.h>
#include "string.h"
#include <math.h>
#include <stdlib.h>
int BinarySearch(double probrnd, double *prob_cumsum, int Ksize) {
int k, kstart, kend;
if (probrnd <=prob_cumsum[0])
return(0);
else {
for (kstart=1, kend=Ksize-1; ; ) {
if (kstart >= kend) {
return(kend);
}
else {
k = kstart+ (kend-kstart)/2;
if (prob_cumsum[k-1]>probrnd && prob_cumsum[k]>probrnd)
kend = k-1;
else if (prob_cumsum[k-1]<probrnd && prob_cumsum[k]<probrnd)
kstart = k+1;
else
return(k);
}
}
}
return(k);}
void gCRSF_gibbs(double *z, double *n_k, double *SampleDex,
double *r, double *a, double *p,
int *Ksize, int *WordNum) {
int i, j, k;
double mass;
double *prob_cumsum;
double cum_sum, probrnd;
void *newptr;
prob_cumsum = (double *) calloc(Ksize[0],sizeof(double));
mass = r[0]*pow(p[0],-a[0]);
for (i=0;i<WordNum[0];i++){
j = (int) SampleDex[i] -1;
k = (int) z[j] -1;
if(z[j]>0){
n_k[k]--;
}
for (cum_sum=0, k=0; k<Ksize[0]; k++) {
cum_sum += n_k[k]-a[0];
prob_cumsum[k] = cum_sum;
}
if ( ((double) rand() / RAND_MAX * (cum_sum + mass) < cum_sum)){
probrnd = (double)rand()/(double)RAND_MAX*cum_sum;
k = BinarySearch(probrnd, prob_cumsum, Ksize[0]);
}
else{
for (k=0; k<Ksize[0]; k++){
if ((int) n_k[k]==0){
break;
}
}
if (k==Ksize[0]){
Ksize[0]++;
newptr = realloc(n_k,sizeof(*n_k)*Ksize[0]);
n_k = newptr;
n_k[Ksize[0]-1]=0;
prob_cumsum = realloc(prob_cumsum,sizeof(*prob_cumsum)*Ksize[0]);
}
}
z[j] = k+1;
n_k[k]++;
}
free(prob_cumsum);}
int main() {
double *z, *n_k, *sampleDex;
double *r, *a, *p;
int *Ksize, *WordNum;
z[0]=1;z[1]=1;z[2]=2;z[3]=0;z[4]=0;
n_k[0]=2;n_k[1]=1;
sampleDex[0]=4;sampleDex[1]=5;
r[0]=5;a[0]=0.5;p[0]=0.5;
Ksize[0]=2;WordNum[0]=2;
gCRSF_gibbs(z,n_k,sampleDex,r,a,p,Ksize,WordNum);
return 0;}
Let's reduce your problem to a minimal example that exhibits the same behaviour:
int main()
{
double *z;
z[0] = 1; // Undefined behaviour!
return 0;
}
Here, z is an uninitialized pointer; it points to a random location. De-referencing it, that is trying to read or write to where the pointer points to leads to undefined behavior.
You use z as an array of 5 floating-point numbers. The easiest way to fix this is to create z as a local array:
double z[5] = {1, 1, 2, 0, 0};
There are probably more errors in your code. This answer addresses only the cause of the obvious segmentation violation.
}
if (k==Ksize[0]){
Ksize[0]++;
newptr = realloc(n_k,sizeof(*n_k)*Ksize[0]);
n_k = newptr;
n_k[Ksize[0]-1]=0;
prob_cumsum = realloc(prob_cumsum,sizeof(*prob_cumsum)*Ksize[0]);
in this piece of code you forgot to add "Invade_Ukraine_Nuclear_Hollocaust_4"
I am very new to C but know my way around [R]. This error could be a very stupid mistake in C.
My C code does kernel smoothing.
*When I comment out the last line of code my function works: results[i] = v; *
This call kills R:
new.y<-zsmooth2( x=c(0:80000), xpts=dat$V2, ypts=dat$V4, h=10000)
* caught segfault *
address 0x1184f8000, cause 'memory not mapped'
Traceback:
1: .C("kernel_smooth", as.double(x), as.double(ypts), as.double(xpts), as.integer(n), as.integer(nxpts), as.double(h), result = double(length(xpts)))
2: zsmooth2(x = c(0:80000), xpts = dat$V2, ypts = dat$V4, h = 10000)
C-code:
#include <R.h>
#include <Rmath.h>
#include <stdio.h>
void kernel_smooth(double *x, double *ypts, double *xpts, int *n, int *nxpts, double *h, double *results){
int i, j;
for(i = 0; i < *n; i++){
double nsum = 0;
double dsum = 0;
double z = x[i] + *h;
double y = x[i] - *h;
for(j = 0; j < *nxpts; j++){
if(xpts[j] < y){
continue;
}
if(xpts[j] > z){
break;
}
double d = (xpts[j] - i) / *h;
double r = dnorm(d, 0, 1, 0);
nsum += r * ypts[j];
dsum += r;
}
Rprintf("test:i %d\n", i);
double v = nsum / dsum;
Rprintf("test:v %f\n", v);
results[i] = v;
}
}
R-code:
dyn.load("~/github/ZevRTricks/smoother1.so")
zsmooth2<-function(x, ypts, xpts, h){
n <- length(x)
nxpts <- length(xpts)
dens <- .C("kernel_smooth", as.double(x), as.double(ypts),
as.double(xpts), as.integer(n), as.integer(nxpts),
as.double(h), result = double(length(xpts)))
dens[["result"]]
}
xpts and ypts are vectors, and in your C code you are trying to access elements 1 to n in each of them. n is the length of x, which is 100 times longer in your second example than in your first example. Compare seq(from = 0, to = 80000 by = 100) to 0:80000, (and while you're at it you can drop the c() from around the 0:80000).
So I guess that xpts and ypts are at least 801 elements long, but less than 80001 elements. You've messed up your indexing somewhere.
Note also that you pass x to your C code, but don't actually use it for anything.
I have filled a dynamic allocated float multi array in a function.
A second function has to get the values of the array exploiting the pointer to the first element of the array defined in the former function.
The second function do not access to the correct memory location so it doesn't work but it does if the multy array is defined in a static way.
Does somebody know why?
eval_cell should get values defined in div_int
float f_imp(float x, float y){
return pow(x,2)+pow(y,2)-1;
}
int eval_cell(float* p){
int s[4];
s[0] = f_imp(*p, *(p+1)) <= 0;
printf("%f %f\n",*p, *(p+1));
s[1] = f_imp(*(p+3), *(p+4)) <= 0;
printf("%f %f\n",*(p+3), *(p+4));
s[2] = f_imp(*(p+9), *(p+10)) <= 0;
printf("%f %f\n",*(p+9), *(p+10));
s[3] = f_imp(*(p+6), *(p+7)) <= 0;
printf("%f %f\n",*(p+6), *(p+7));
printf("%d%d%d%d\n",s[0],s[1],s[2],s[3]);
return s[0];
}
void div_int(float* x1, float* y1,float* x2,float* y2,
float* f0, float* f2,float* f6,float* f8){
int i,j,m;
float* p;
float** a_cell; // array 9x3 contente coordinate vertici e valore funzione
*a_cell = (float**) malloc(9*sizeof(float*));
for (i=0;i<9;i++){
a_cell[i] = (float*) malloc(3*sizeof(float));
}
a_cell[0][0] = *x1;
a_cell[0][1] = *y1;
a_cell[0][2] = *f0;
a_cell[2][0] = *x2;
a_cell[2][1] = *y1;
a_cell[2][2] = *f2;
a_cell[6][0] = *x1;
a_cell[6][1] = *y2;
a_cell[6][2] = *f6;
a_cell[8][0] = *x2;
a_cell[8][1] = *y2;
a_cell[8][2] = *f8;
/*** calcolo dei valori incogniti di a_cell ***/
a_cell[1][0] = (*x1+*x2)/2;
a_cell[1][1] = *y1;
a_cell[1][2] = f_imp(a_cell[1][0], a_cell[1][1]);
a_cell[3][0] = *x1;
a_cell[3][1] = (*y1+*y2)/2;
a_cell[3][2] = f_imp(a_cell[3][0], a_cell[3][1]);;
a_cell[4][0] = (*x2+*x1)/2;
a_cell[4][1] = (*y2+*y1)/2;
a_cell[4][2] = f_imp(a_cell[4][0], a_cell[4][1]);
a_cell[5][0] = *x2;
a_cell[5][1] = (*y2+*y1)/2;
a_cell[5][2] = f_imp(a_cell[5][0], a_cell[5][1]);
a_cell[7][0] = (*x1+*x2)/2;
a_cell[7][1] = *y2;
a_cell[7][2] = f_imp(a_cell[7][0], a_cell[7][1]);
for (j=0;j<2;j++){
m = j*3;
for(i=0;i<2;i++){
m += i;
eval_cell(&a_cell[m][0]);
}
}
p = *a_cell;
for (i=0;i<9;i++){
for (j=0;j<3;j++){
printf("%f \n",*(p+3*i+j));
printf("%f \n",a_cell[i][j]);
printf("\n");
}
}
free(a_cell);
return;
}
It's because you using pointer in incorrect way:
See a_cell is pointer to dynamic array of 9 pointers to dynamic array of 3 floats.
So when you do eval_cell(&a_cell[m][0]) (or just eval_cell(a_cell[m]) this is actually the same) you actually get pointer to array of 3 floats. And after that you do:
int eval_cell(float* p){
...
s[2] = f_imp(*(p+9), *(p+10)) <= 0;
*(p+9) will get 9th element in array of 3 floats, so this is incorrect.
It works in static way, because static multi dimension array in memory is just one dimension array for which you was given multi indexing (by compiler). That's why in static you will probably address valid memory area.
See picture for more explanation:
If you want a completely dynamic matrix (2d array), you have to make your own element access function:
double *
make_array (unsigned int rows, unsigned int cols)
{
return malloc (rows * cols * sizeof (double));
}
double *
array_element (double *a, unsigned int cols, unsigned int i, unsigned int j)
{
return a + i * cols + j;
}
#define A(i,j) (*array_element ((a), (cols), (i), (j)))
double *a;
unsigned int rows, cols;
a = make_array (rows, cols);
A(3,4) = 3.14;
printf ("%f\n:" A(3,4));
EDIT:
In your program
*a_cell = (float**) malloc(9*sizeof(float*));
should be
a_cell = (float**) malloc(9*sizeof(float*));
And likewise for
p = *a_cell;