Im building a simple error checking system and get the error:
/tmp/ccNY7emi.o:(.data+0x0): multiple definition of `error_desc'
/tmp/ccMI89tg.o:(.data+0x0): first defined here
collect2: error: ld returned 1 exit status
using gcc on Linux, the code is next, i believe is very self explanatory,
im not an expert on C, must be error_desc
declared as extern
? and how?
error.h
#ifndef ERROR_H_
#define ERROR_H_
typedef enum error_e {
ERR_DB_CONN_FAIL, ERR_BAD_PARAM, ERR_NET_CONN, ERR_STR_TO_LONG
} error_e;
char *error_desc[] = {
"Fail to connect database",
"invalid parameter",
"Cannot connect to the network",
"String length exceed established limit",
};
char *error_str(error_e err);
#endif
error.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "error.h"
unsigned get_arr_size(char **arr) {
int count = 1;
while (*++arr) {
++count;
}
return count;
}
char *error_str(error_e err) {
unsigned arr_size = get_arr_size(error_desc);
if ((unsigned)err < arr_size) {
return error_desc[err];
}
return "Invalid error code";
}
use-error.c
#include <stdio.h>
#include "error.h"
int main(void){
printf("Error: %s\n", error_str(ERR_NET_CONN));
printf("Error: %s\n", error_str(ERR_STR_TO_LONG));
printf("%s\n", error_str(6));
}
If i move declaration/initialization of error_str
to error.c it works, but i prefer
have error_e
and error_str
due to "mapping" relation between them.
I modify main.c
:
#include "error.h"
int main(void){}
And examine the preprocessor output and get this:
gcc use-error.c error.c -E > prep.c
prep.c
# 1 "use-error.c"
# 1 "<command-line>"
# 1 "use-error.c"
# 1 "error.h" 1
typedef enum error_e {
ERR_DB_CONN_FAIL, ERR_BAD_PARAM, ERR_NET_CONN, ERR_STR_TO_LONG
} error_e;
static char *error_desc[] = {
"Fail to connect database",
"invalid parameter",
"Cannot connect to the network",
"String length exceed established limit",
};
char *error_str(error_e err);
# 4 "use-error.c" 2
int main(void){
}
# 1 "error.c"
# 1 "<command-line>"
# 1 "error.c"
# 1 "error.h" 1
typedef enum errors {
ERR_DB_CONN_FAIL, ERR_BAD_PARAM, ERR_NET_CONN, ERR_STR_TO_LONG
} errors_e;
static char *error_desc[] = {
"Fail to connect database",
"invalid parameter",
"Cannot connect to the network",
"String length exceed established limit",
};
char *error_str(errors_e err);
# 2 "error.c" 2
static unsigned get_arr_size(char **arr) {
int count = 1;
while (*++arr) {
++count;
}
return count;
}
char *error_str(error_e err) {
unsigned arr_size = get_arr_size(error_desc);
if ((unsigned)err < arr_size) {
return error_desc[err];
}
return "Invalid error code";
}
It looks like preprocessor is ignoring the header guards, but why?
By the way, if declare static
(that doesn't make many sense, i'll make it only to explore)
the variable error_desc
the code gets built, but if i use -Wall
option on gcc i get the message:
warning: ‘error_desc’ defined but not used [-Wunused-variable]
If the code on error.c
isn't using error_desc
from error.h
, then from where?