简体   繁体   中英

Trouble with allocating a variable to an array element

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM