NO

Author Topic: Dynamic arrays  (Read 3308 times)

Offline iwrbc

  • Member
  • *
  • Posts: 16
Dynamic arrays
« on: April 10, 2021, 12:13:23 AM »
Hi, I am working on a program where I use dynamic arrays. I do this because the size of the array depends on the contents of files (not known at compile time) and user input (also not known at compile time). The contents of the array need to be accessible all over the program. The user may run the program one, two or many times, with same or different input. At one point in my program I use this, which runs without problems:
Code: [Select]
  if (WorkCompon == NULL) { //first time
    WorkCompon = (struct WorkComponentType*)calloc((RawNumCompon * 2 + 400), sizeof(struct WorkComponentType));
  } else { //second time here or later; RawNumCompon may be different here than first time
    WorkCompon = (struct WorkComponentType*)realloc(WorkCompon, (RawNumCompon * 2 + 400) * sizeof(struct WorkComponentType));
  }

A little further down I get something similar (I think):
Code: [Select]
  //create new two-dimensional array
  if (WorkMat == NULL) { //first time
    WorkMat = (struct WorkMatType*)calloc(((MaxNumBBWork) * (WorkNumSpec)), sizeof(struct WorkMatType));
  }
  else { //second time or later; MaxNumBBWork  and WorkNumSpec  may be different than first time
    WorkMat = (struct WorkMatType*)realloc(WorkMat, (MaxNumBBWork * WorkNumSpec * sizeof(struct WorkMatType)));
  }
which results in a error "Exception: C0000374". I do not understand what I am doing wrong.
FYI: in an include file I declare:
Code: [Select]
struct WorkMatType {
  long Pointer2Component;
  long StoichCoef;
};

struct WorkMatType *WorkMat;

I also tried to free the memory and allocate like:
Code: [Select]
  //create new two-dimensional array
  if (WorkMat == NULL) { //first time
    WorkMat = (struct WorkMatType*)calloc(((MaxNumBBWork) * (WorkNumSpec)), sizeof(struct WorkMatType));
  }
  else { //second time or later
    free (WorkMat);
    WorkMat = (struct WorkMatType*)calloc(((MaxNumBBWork) * (WorkNumSpec)), sizeof(struct WorkMatType));
  }

but that also leads to the same error.

I think it must be something simple as I am not yet so familiar with C. Any help to solve this issue is appreciated.

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: Dynamic arrays
« Reply #1 on: April 10, 2021, 01:26:22 PM »
First of all you should show us a minimal reproducible example, i.e. a miniproject with few units and headers, that compiled show the problem.
It is very difficult to understand by this few lines of code where is the problem.
I.e. if you declare:
Code: [Select]
struct WorkMatType *WorkMat;In an header file that can be included in more units (C files) you should get an error about symbol multiply defined.
If for some reason you was able to define it in multiple units it could result to be undefined or uninitialized, then the error.
Maybe you meant:
Code: [Select]
extern struct WorkMatType *WorkMat;
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

Offline iwrbc

  • Member
  • *
  • Posts: 16
Re: Dynamic arrays
« Reply #2 on: April 10, 2021, 01:50:32 PM »
OK, I will try to setup what you ask. Could be that the problem is there because I have an header file with the definitions which I include in all modules.
So, how should it be done then? You define the structure in main file, and in the others you  refer to it with extern keyword? I come back, thanks so far.

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: Dynamic arrays
« Reply #3 on: April 10, 2021, 06:49:26 PM »
You have to distinguish between definitions and declarations.
When you define a type you are defining an alias name for a variable type, scalar or aggregate. I.e. in:
Code: [Select]
struct WorkMatType {
  long Pointer2Component;
  long StoichCoef;
};
You define in structures namespace an alias WorkMatType as a new aggregate variable type.

Then you can instantiate variables, direct or derivate, using the alias type name in a declaration. The following line shows an example for direct and derivate type, in this case a pointer to the structure:
Code: [Select]
struct WorkMatType WorkMat;        //direct type
struct WorkMatType *WorkMatPtr;  //derivate type, a pointer

In header files, normally you will put definitions of types; if you put a variable declaration, that variable will be instantiate in any module that include the header.
The result generally is a multiply symbol definition error in the linking phase. But if you define as static a variable with same name as the global one, the error will not be present, and the compiler will create a local copy of the variable that will be referred in the whole module instead of the global one.

If you want to define a global variable to be used in all modules you have to insert in the header an extern definition that doesn't instantiate a variable, but instruct the linker to refer to the global symbol with that name. I.e.
Code: [Select]
extern struct WorkMatType *WorkMat;        //extern definition in header file
Then you will instantiate the global variable in one, and only one, module using the declaration:
Code: [Select]
struct WorkMatType *WorkMat;        //this declaration will instantiate this variable. To be used in one module only.
« Last Edit: April 10, 2021, 09:20:17 PM by frankie »
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2115
Re: Dynamic arrays
« Reply #4 on: April 11, 2021, 08:13:09 AM »
Might be safer in C
Code: [Select]
typedef struct _WorkMatType {
  long Pointer2Component;
  long StoichCoef;
} WorkMatType;
in header file
Code: [Select]
extern WorkMatType *WorkMat;simple test use only realloc
Code: [Select]
#include <stdlib.h>
#include <stdio.h>

typedef struct _WorkMatType {
  long Pointer2Component;
  long StoichCoef;
} WorkMatType;

WorkMatType *WorkMat;


int __cdecl main(void)
{
int MaxNumBBWork = 10;
int WorkNumSpec = 5;
WorkMat = (WorkMatType*)realloc(WorkMat, (MaxNumBBWork * WorkNumSpec * sizeof(WorkMatType)));
printf("WorkMat %ph, MaxNumBBWork %d\n", WorkMat, MaxNumBBWork);
MaxNumBBWork = 100;
WorkMat = (WorkMatType*)realloc(WorkMat, (MaxNumBBWork * WorkNumSpec * sizeof(WorkMatType)));
printf("WorkMat %ph, MaxNumBBWork %d\n", WorkMat, MaxNumBBWork);
free(WorkMat);
return 0;
}
May the source be with you

Offline John Z

  • Member
  • *
  • Posts: 860
Re: Dynamic arrays
« Reply #5 on: April 11, 2021, 04:15:44 PM »
TimoVJL & frankie - kudos to you both for the comprehensive help you are providing iwrbc!
Some of the best instructive help I've seen here.


John Z

Offline iwrbc

  • Member
  • *
  • Posts: 16
Re: Dynamic arrays
« Reply #6 on: April 11, 2021, 05:02:31 PM »
Great, thanks to all of you. (sorry, didn't have time to reply earlier)