multiple definition in g++? - c

The code is as follows:
global.h
#ifndef GLOBAL_H
#define GLOBAL_H
#include <stdio.h>
int test;
void test_fun(void);
#endif
global.c
#include "global.h"
void test_fun()
{
printf("%d\n", test);
}
main.c
#include "global.h"
int main(void)
{
test_fun();
test = 1;
printf("%d\n", test);
}
Makefile using gcc compiler
main: main.o global.o
gcc -o main main.o global.o
main.o: main.c global.h
gcc -c main.c
global.o: global.c global.h
gcc -c global.c
clean:
rm -f global.o main.o main
This works well.
However, when I change my code to C++, as follows:
global.h
#ifndef GLOBAL_H
#define GLOBAL_H
#include <iostream>
int test;
void test_fun(void);
#endif
global.cpp
#include "global.h"
void test_fun()
{
cout << test
}
main.cpp
#include "global.h"
int main(void)
{
test_fun();
test = 1;
std::cout << test;
}
Makefile using g++ compiler
main: main.o global.o
g++ -o main main.o global.o
main.o: main.cpp global.h
g++ main.cpp
global.o: global.cpp global.h
g++ global.cpp
clean:
rm -f global.o main.o main
The code above throws the output:
global.o:(.bss+0x0): multiple definition of `test'
What makes the different here?

You've int test; in a header which is included in 2 TUs, hence the error. Both the translation units main.c (or .cpp depending upon the compiler used) and global.c have global.h included, which leads to two definitions of the same variable in two object files, thus the linker error.
Pass test as an arguement to test_fun, thereby avoiding the usage of a global.
If you absolutely have to share the variable between the TUs, then remove int test; from global.h and in main.cpp do
int test;
and in global.cpp do
extern int test;
As an aside, since it's a global variable, test would be initialized to 0 and hence in main when you test_fun();, it should print 0 and then after setting it to 1, it'll print 1.
It's illegal in both C and C++ from a language standpoint, but as for why it works with a C compilers (like GCC) is because they implement a common extension, a legacy cruft.

... You are using a different programming language

Related

linking with wrap directive for unit testing can be used to redefine a subroutine?

I'm using Cmocka to write a unit testing suite for a shared object written in C, but I'm having some issue. Since I cannot share the source code, I have written a minimum "not-working" example to show what is the issue:
my program is composed 5 files: foo.c, foo.h bar.c bar.h main.c.
bar.* files define a bar() function, which simply returns the argument multiplied by 2
foo.* files declare a foo() function that uses the bar() function defined by bar.h
main.c contains a simple cmocka test and a __wrap_bar()
function, returning the argument multiplied by 3.
I compile the program by producing a libfootest.so object (foo+bar) and then I link this object with main.o passing the -Wl,--wrap=bar flag to the compiler. In this configuration libfootest is the module under test and main is the tester program. I expect the __wrap__bar to be called (failing the test), but the standard bar() is called(test is passed). How can I solve this problem? Below you find all the code I'm using.
bar.c:
#include "bar.h"
int bar(int val) {
return val*2;
}
bar.h:
int bar(int val);
foo.h:
#include <stdio.h>
int foo(int val);
foo.c:
#include "foo.h"
#include "bar.h"
int foo(int val) {
int ret;
ret = bar(val);
printf("RET: %d", ret);
return ret;
}
main.c:
#include <stdio.h>
//required include for CMOCKA
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <setjmp.h>
#include <cmocka.h>
//library under test
#include "foo.h"
int __wrap_bar(int val) {
return 3*val;
}
static void test_foo(void **state) {
int ret = foo(5);
assert_int_equal(ret, 10);
}
int main (int argc, char** argv) {
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_foo),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}
Makefile:
CMOCKA_LIB_DIR=../../cmocka-1.1.5/build/src
CXXFLAGS+=-g -Og -fPIC
CFLAGS+=-g -Og -std=c99 -fPIC
CC=gcc
CXX=g++
all: main.o ./libfootest.so
gcc -o linux-test -g -L. -L$(CMOCKA_LIB_DIR) $(filter %.o, $^) -lcmocka -lfootest -Wl,-rpath=. -Wall -Wl,--wrap=bar -Wl,-rpath=$(CMOCKA_LIB_DIR)
./libfootest.so: foo.o bar.o
$(CC) -shared -o $# -g $^ -pedantic -Wall
clean:
rm -f *.o
rm -f *.so
The problem is your build of the library. You don't create a link library as commonly done, with separated modules. Instead you link all given modules and place the resulting single module in the target library.
That's why the linker resolved the call to bar() already, and it is no longer unresolved when linking the test program.
The option --wrap works only for unresolved references between modules.
The solution is to build the library from separated modules. Use the tool ar for this:
ar r libfootest.a foo.o bar.o

How to deal with function definitions in header files?

Is there any way I can compile a poorly designed header file to a object file without changing file extension or content using gcc, or do I have to copy the file/edit it? (This because I am using a public SDK, i.e. I do not have permission to edit the header file, and because using cp in my Makefile seems like a major hack, and time consuming too)
Example
main.c
#include <print.h>
#include <app.h>
int main(void) {
print("Starting app . . . ");
run();
}
app.h
#ifndef APP_H
#define APP_H
int runApp(void);
#endif
app.c
#include <print.h>
#include <app.h>
int runApp(void) {
print("This is my app!");
return 0
}
print.h
#ifndef PRINT_H
#define PRINT_H
int print(char* str) {
printf(str);
return 0;
}
#endif
Which is compiled using:
$ gcc -o main.o main.c
$ gcc -o app.o app.c
$ gcc -o main main.o app.o
The SDK example programs use a single object file (gcc -o main.o main.c & gcc -o main main.o), but that would just get really messy in my case.
Create
_print.h
int print(char* str);
print.cpp
#include <print.h>
and change your includes to "_print.h"

Issues with .h files in C

I created a sample .h file in C and it didn't work, for some reason. The files are as follows:
header.c:
#include <stdio.h>
#include "header.h"
int add(int a, int b) {
int tmp=a;
int i;
for(i=0, i==tmp, i++) {
b++;
}
return(b);
}
header.h:
#ifndef HEADER_H
#define HEADER_H
int add(int a, int b);
#endif
main.c:
#include <stdio.h>
#include "header.h"
int main(void) {
int foo=add(1, 2);
printf("%i \n", foo);
return(0);
}
When I try to compile main.c with make and gcc it says that add is undefined. Help!
You need to compile both main.c and header.c into the same executable:
all: main
main: main.o header.o
gcc -o main main.o header.o
header.o: header.c header.h
gcc -c header.c
main.o: main.c header.h
gcc -c main.c
Or for a one-liner without a make file:
gcc -g -o main main.c header.c
Including the header file only includes the function prototype. You need to link the actual definition of add() by compiling separate object files or you can compile them together in a single command line:
gcc -Wall -Wextra header.c main.c -o main
Perhaps, you may want to consider Makefiles for larger projects.
Your add() function has issues:
1) Semi-colons ; are used in for loops, not commas.
2) The condition should be i!=tmp for addition.
This:
for(i=0, i==tmp, i++) { .. }
should be
for(i=0; i!=tmp; i++) { .. }
You need to add header.c to the compile call. You can't just compile main.c.

Linking files having multiple main function in c

Is it possible to link two C files using makefile which calls each other function but both have a main function of their own.
e.g:
C1.c uses function f() from C2.c.but both have main function and I want the main in C1.c to be considered as main only.
FILES.o=set.o hash.o printnfa.o input.o nfa.o dfa.o terp.o minimize.o defnext.o print_ar.o pairs.o squash.o signon.o print.o lex.o assort.o prnt.o printv.o bintoasc.o ferr.o onferr.o fputstr.o pchar.o driver.o searchenv.o hashadd.o esc.o
PROGRAM= Lexer
INC := -I./debug.h -I./global.h -I./stack.h -I./set.h -I./hash.h
CFLAGS=-DMAIN
all: ${PROGRAM}
${PROGRAM}: ${FILES.o}
${CC} -o $# ${CFLAGS} $(INC) $^ ${LDFLAGS} ${LDLIBS}
Now terp.c has a main and lex.c also has a main. I want only the main for lex.c to be considered.
This will be specific for the linker you use. On Linux you can pass the --allow-multiple-definition flag to the linker in order to use only the first symbol in case of multiple definitions:
${PROGRAM}: ${FILES.o}
${CC} -Xlinker --allow-multiple-definition -o $# ${CFLAGS} $(INC) $^ ${LDFLAGS} ${LDLIBS}
This will omit all errors about duplicate symbols and cause the linker to ignore any redefinitions. Make sure that the object file containing the symbol you wish to use comes before any redefinitions in the list.
The short answer... NO ... it is NOT possible
First of all I would recommend that you refactor the code so that you don't have functions that will be used by many programs in the same file as a main function.
Any way, here is an example on how to use the pre-processor to include only one of the main functions.
We have two source code files both with a main function plus one other function, foo() in file1.c and bar() in file2.c. foo() and baa() are called from both of the main functions.
By changing the MAIN_ALT value in the Makefile we can switch between the main functions:
Use the main function in file1.c:
DEFINES += -DMAIN_ALT=1
Use the main function in file2.c:
DEFINES += -DMAIN_ALT=2
Makefile:
OBJS = file1.o file2.o
DEFINES += -DMAIN_ALT=1
CFLAGS += -Wall $(DEFINES)
prog:$(OBJS)
$(CC) $(CFLAGS) -o $# $^
file1.c:
#include "stdio.h"
#include "def.h"
void foo(){
printf("From foo\n");
}
#if MAIN_ALT == 1
int main(){
printf("Main in file1.c\n");
bar();
foo();
return 0;
}
#endif
file2.c:
#include "stdio.h"
#include "def.h"
void bar(){
printf("From bar\n");
}
#if MAIN_ALT == 2
int main(){
printf("Main in file2.c\n");
bar();
foo();
return 0;
}
#endif
def.h:
#ifndef __DEF_H__
#define __DEF_H__
void foo();
void bar();
#endif

Undefined function in CC compiler (minix)

I have a mysterious problem!
In the main.c I have the following:
#include "jogo.h"
int main(){
int i;
sef_startup();
vg_init(0x105);
batalha_naval();
sleep(5);
vg_exit();
return 0;
}
In the jogo.h I have:
#ifndef __JOGO_H
#define __JOGO_H
void batalha_naval(void);
#endif
And in the main.c I have:
#include "core.h"
void batalha_naval(void) {
vg_draw_line(0, 0, 1023, 0, 12);
}
But when doing a make the compiler gives a undefined _batalha_naval(); in the main.c. If I define the function in the jogo.h an error doesn't appear, but if I do like this the error appears.
I am using CC compiler.
Your jogo.h appears correct.
You need it if you wish to use function "batalha_naval()" in multiple compilation units.
You should '#include "jogo.h"' in main.c, and in jogo.c.
You must include both main and jogo in your link command.
How are you linking? You need to do either:
$ cc -c main.c
$ cc -c jogo.c
$ cc main.o jogo.o
or
$ cc main.c jogo.c

Resources