using "extern" incorrectly not detected

sb
2008-02-02
2013-03-12
  • sb
    sb
    2008-02-02

    When declaring external variables using either different memory area or different type, the compiler gives no compile error og warning.

    Declaring for instance an "unsigned char var1" in one of the source files of the project, and then using this in the main source file of the project by declaring it as "external unsigned int var1" by mistake, the compiler does not give any errors or warnings.

    When looking at the assembly code, the variables is treated as an integer in the main source file, and as a char in the "external" source file, leading to misbehaviour and possible corruption of other variables.

    If the variable is declared with the __xdata directive in the original declaration but this is ommited by mistake in the main source file, the variable is access using movx.. in the sourcefile where the __xdata directive was used, and with normal mov.. in the source file where the __xdata was omitted.

    Other compilers complain about this as redefinition, which I believe is the most correct behaviour.

    What does the ANSI specification say about this, and what is the common practice with other compilers regarding this issue ?

     
    • Maarten Brock
      Maarten Brock
      2008-02-04

      Put the extern declaration in a header file and include it especially in the file that has the definition. Then the compiler has a chance to detect your error and warn about it.

       
    • I believe that an ANSI C compiler should flag up that var1 has two different types, such as char and int. The 8051 specific type modifiers (e.g. __xdata) are not part of any C standard, so you can't say what the compiler behaviour should be.

       
      • Maarten Brock
        Maarten Brock
        2008-02-06

        Yes, the compiler should warn you and it does so. But I don't think the linker also has to warn you. The linker doesn't know about all the different types you could define with a typedef.

         
        • sb
          sb
          2008-02-09

          I have put all my "external" declarations inside the header files of the modules which exports the variables, and this works well.

          I have however also tried to reduce the overall use of the extern keyword in general.

          Since SDCC compiles one file at a time, I can understand that the compiler will not be able to detect the different declarations before both declarations have been evaluated, and the linker would be the place to detect the kind of difference in declaration I mentioned as the problem.

          This is however possible if the "extern" declaration is put inside a header file wich is included in the source file containing the original declaration. SDCC then detects the difference between the two declarations when parsing the resulting file which then contains both declarations.

          I have however used the Raisonance compiler for other projects, which was able to detect differing declarations in different source files of the project, and that was the reason for my opening of this discussion.

           
          • I've also used toolsets where the linker detects the mismatch, so I would agree that SDCC is weak in this area.

            I don't understand the purpose of reducing extern declarations. I understand the benefit of reducing the use of global variable, shared across compilation modules, as they allow interactions that are hard to follow. A lot of extern declarations are a symptom, not a cause.

             
            • sb
              sb
              2008-02-11

              I haven't really used the extern declaration before splitting up this project into separate modules in order to split the total application into logical groups of code (LCD handling, menu output, keyboard handling, buffer handling, serial communication handling, time handling etc.), and found that to be a way to access variables across the modules.

              As the code increases to several thousand lines of code, it may be harder to keep track of the global variables if not named properly.

              Hiding or encapsulating the variables inside the modules in which they are used makes the code easier to maintain, but may have to be optimized if memory usage becomes an issue.