NO

Author Topic: Compiler Checks  (Read 359 times)

Offline John Z

  • Member
  • *
  • Posts: 157
Compiler Checks
« on: January 16, 2021, 02:25:18 pm »
So I know this was a rookie mistake, but it took me hours to figure out a memory corruption issue.  Maybe the compiler can help.
Type checking and sizing are routine in the compiler such as char vs. wchar_t, or int to long int.

My error was in one module I had declared a global array like int a[11][7][40]; in another module I needed to access this variable.  So I put it in as extern int a[11][7][40]; - so far so good.  Everything fine, worked great.  By module I mean a C procedure file.

Now my mistake was created by changing the original int a to int a[11][8][40];.  The program worked fine everywhere until I tried to use element [8] in the module where it was extern. Of course when I finally found and changed the extern a to the new a[11][8][40]; everything was good again.

So it seems that the compiler does not check any extern declaration against the  'original' declaration.  This includes procedure declarations and well as variable declarations.

Is it worthwhile and possible to implement such checks? Perhaps is it such a rookie mistake not worth the code …..

Anyway I learned to be careful with using extern  :)

John Z

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 1792
Re: Compiler Checks
« Reply #1 on: January 16, 2021, 05:02:01 pm »
The problem is that the symbols binding happen in the linking phase when any type qualification is lost.
So I think it is not as simple to achieve.
This configures what normally is called 'magic numbers', the use of wild numbers vs speaking symbols.
I.e.in your case would have been better:
Code: [Select]
#define FIRST_SUBSCRIPT    11
#define SECOND_SUBSCRIPT    8
#define THIRD_SUBSCRIPT    40
int a[FIRST_SUBSCRIPT][SECOND_SUBSCRIPT][THIRD_SUBSCRIPT];
While waiting for Pelle's comments, I would suggest to use a typedef.
Define prototype in a global header:
Code: [Select]
typedef int int_array_t[11][8][40];or better:
Code: [Select]
typedef int int_array_t[FIRST_SUBSCRIPT][SECOND_SUBSCRIPT][THIRD_SUBSCRIPT];Then define extern references as:
Code: [Select]
extern int_array_t int_array;The variable can then be declared in a single module as in the following example where we initialize only the very first element to 1:
Code: [Select]
int_array_t int_array = {{{{1}}}};Pro's: Unique definition less prone to errors.
con's: Less readable
« Last Edit: January 16, 2021, 05:13:00 pm by frankie »

Offline John Z

  • Member
  • *
  • Posts: 157
Re: Compiler Checks
« Reply #2 on: January 16, 2021, 05:22:22 pm »
Thanks Frankie,

I did not know which phase it happened in.  Good to know.

Thanks for the suggestions, I've used both of these at one time or another - this time went the 'magic numbers' way... and it magically frustrated me for 4 hours ….   

HaGD,

John Z
 

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 1792
Re: Compiler Checks
« Reply #3 on: January 16, 2021, 06:33:20 pm »
John, are always the simplest issues to waste the vast majority of time...  >:(
That's programming!  ;)

Offline Pelle

  • Administrator
  • Member
  • *****
  • Posts: 2101
    • http://www.smorgasbordet.com
Re: Compiler Checks
« Reply #4 on: January 17, 2021, 06:20:59 pm »
Frankie has already explained why not (C is not C++ with name mangling), and given some ideas how to declare the array.

All I can add is this:
if you have an object (array, function, whatever) referenced from multiple C files, you always place a declaration of that object in a header file (*.h) and make sure it's included from all C modules. This is pretty basic stuff.

/Pelle

Offline John Z

  • Member
  • *
  • Posts: 157
Re: Compiler Checks
« Reply #5 on: January 18, 2021, 02:40:10 am »
Yes, yes it is.

John Z