Pages: [1]   Go Down
Author Topic: Multiple Inclusion Bug  (Read 627 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm fairly certain this is a bug with the compiler, but just to be sure I am not making a silly mistake...

I have two files that include the same header file.

The header file looks like this:

Code:
#ifndef GYRO_H
#define GYRO_H

/*
This is a list of registers in the ITG-3200. Registers are parameters that
determine how the sensor will behave, or they can hold data that represent the
sensors current status. To learn more about the registers on the ITG-3200,
download and read the datasheet.
*/
char WHO_AM_I = 0x00;
char SMPLRT_DIV= 0x15;
char DLPF_FS = 0x16;
char GYRO_XOUT_H = 0x1D;
char GYRO_XOUT_L = 0x1E;
char GYRO_YOUT_H = 0x1F;
char GYRO_YOUT_L = 0x20;
char GYRO_ZOUT_H = 0x21;
char GYRO_ZOUT_L = 0x22;

/*
This is a list of settings that can be loaded into the registers.
DLPF, Full Scale Register Bits
FS_SEL must be set to 3 for proper operation
Set DLPF_CFG to 3 for 1kHz Fint and 42 Hz Low Pass Filter
*/
char DLPF_CFG_0 = 1<<0;
char DLPF_CFG_1 = 1<<1;
char DLPF_CFG_2 = 1<<2;
char DLPF_FS_SEL_0 = 1<<3;
char DLPF_FS_SEL_1 = 1<<4;

/*address of gyro on I2C*/
char itgAddress = 0x68;

/*write and read addressed on i2c for Gyro*/
void itgWrite(char address, char registerAddress, char data);
unsigned char itgRead(char address, char registerAddress);

/*get x, y, and z axis angular rates from gyro*/
int gyroReadX(void);
int gyroReadY(void);
int gyroReadZ(void);

#endif

Note the #ifndef/#define/#endif preprocessor directives.


Two files (myproject_gyrotest.ino and Gyro.cpp) include this "Gyro.h" via:

Code:
#include "Gyro.h"

I get the following errors when compiling:

Code:
myproject_gyrotest.cpp.o:(.data.itgAddress+0x0): multiple definition of `itgAddress'
Gyro.cpp.o:(.data.itgAddress+0x0): first defined here
c:/arduino/arduino-1.0.2-windows/arduino-1.0.2/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/bin/ld.exe: Disabling relaxation: it will not work with multiple definitions

along with tons of other multiple inclusion problems.


I mean, am I being a complete idiot, or is this another compiler bug? (There are several other bugs with this Arduino compiler I have found the hard way that are documented elsewhere).

Compiler version: 1.0.2 Windows 7 (x86)
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13072
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
...or is this another compiler bug?

No.
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 212
Posts: 8974
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Since two files include Gyro.h they each create a global char variable called "itgAddress".

Is that value a constant?  If so you should write it as:
Code:
const char itgAddress = 0x68;

If the value needs to be an initialized variable you should change the header file to make that an external reference:
Code:
extern char itgAddress;
and in the file where it makes the most sense, define the variable and its value:
Code:
char itgAddress = 0x68;
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

#defines are only defined within the compilation unit. You *want* each compilation unit to have your header file included exactly once. You *don't* want to do anything that allocates memory in a header file.
Logged

Offline Offline
God Member
*****
Karma: 32
Posts: 830
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You *don't* want to do anything that allocates memory in a header file.

In particular, change things like

char DLPF_FS_SEL_1 = 1<<4;

to

#define DLPF_FS_SEL_1 1<<4

so there isn't any memory allocation involved in your definitions.

I'd further recommend puttings the expression parenthesis, like this

#define DLPF_FS_SEL_1 (1<<4)

to make it a bit more robust.
Logged

WiFi shields/Yun too expensive? Embeddedcoolness.com is now selling the RFXduino nRF24L01+ <-> TCP/IP Linux gateway: Simpler, more affordable, and even more powerful wireless Internet connectivity for *all* your Arduino projects! (nRF24L01+ shield and dev board kits available too.)

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 639
Posts: 34724
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
(There are several other bugs with this Arduino compiler I have found the hard way that are documented elsewhere).
Care to shair what these are?
Logged

Offline Offline
God Member
*****
Karma: 32
Posts: 830
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
(There are several other bugs with this Arduino compiler I have found the hard way that are documented elsewhere).
Care to shair what these are?

Google is your friend. Here's a sampling of some of my favorites:

http://code.google.com/p/arduino/issues/list?can=2&q=preprocessor&colspec=ID+Type+Status+Priority+Milestone+Owner+Summary&cells=tiles
Logged

WiFi shields/Yun too expensive? Embeddedcoolness.com is now selling the RFXduino nRF24L01+ <-> TCP/IP Linux gateway: Simpler, more affordable, and even more powerful wireless Internet connectivity for *all* your Arduino projects! (nRF24L01+ shield and dev board kits available too.)

Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, johnwasser, for the post. I have since changed all of my allocated variables to pound defines to avoid the problem I was having. I will take your advice in the future about using const and externs.

Though, this http://code.google.com/p/arduino/issues/detail?id=906&q=preprocessor documented problem seems to be exactly what I've been fighting for a while.

While two files include "Gyro.h", the pre-processor directives should indicate to the compiler to only create one copy of Gyro.h and link the other files against it, which (I would think) prevent the multiple inclusion problem.

I will switch to my Ubuntu drive in a minute to see how gcc handles this situation.
Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, johnwasser, for the post. I have since changed all of my allocated variables to pound defines to avoid the problem I was having. I will take your advice in the future about using const and externs.

Though, this http://code.google.com/p/arduino/issues/detail?id=906&q=preprocessor documented problem seems to be exactly what I've been fighting for a while.

While two files include "Gyro.h", the pre-processor directives should indicate to the compiler to only create one copy of Gyro.h and link the other files against it, which (I would think) prevent the multiple inclusion problem.

I will switch to my Ubuntu drive in a minute to see how gcc handles this situation.


.h files aren't compiled. The compiler literally replaces the #include line with the file you want to include, so the contents of the .h file exist in every compiled file (.c, .cpp, .ino, .pde) that includes it. The include guards (#ifndef... #define) prevent the contents of the .h file to be copied in twice, but it will still be copied in every compiled file that includes it.
Logged

Pages: [1]   Go Up
Jump to: