multiple definition of a function - c++

I defined a function to show a message when debug flags are off in a header file as below:
#ifdef NDEBUG
#define debug_msg(expr, msg) (static_cast<void>(0))
#else /* Not NDEBUG. */
#ifndef SHOW_DEBUG_H_
#define SHOW_DEBUG_H_
#include <stdio.h>
void _show_in_debug(const char *_file, unsigned int _line,
const char *_function, const char *_msg)
{
printf("%s\t%d\t%s\t%s\n", _file, _line, _function, _msg);
fflush(NULL);
}
#endif
#define debug_msg(expr, msg) \
((expr) \
? _show_in_debug(__FILE__, __LINE__, __func__, msg) \
: static_cast<void>(0))
#endif
when I include the header in more than a file, I get the following error:
multiple definition of `_show_in_debug(char const*, unsigned int, char
const*, char const*)'
I don't exactly know what I am doing wrong here, any help ?

Even with the include guards, you end up with a definition of _show_in_debug in each compilation unit. Linking those units then results to a multiple definition error.
For a debugging function like this, define the function as static so that it is not visible outside its compilation unit:
static void _show_in_debug(const char *_file, unsigned int _line,
const char *_function, const char *_msg)
{
printf("%s\t%d\t%s\t%s\n", _file, _line, _function, _msg);
fflush(NULL);
}

If you include that header into more than one .c file, each of them will define the function. That is what the error says.
What you should do is to only declare the function in the header (i.e. only put the prototype there; which you always should) and then define it in a single .c file (i.e. put the body in the .c file), encapsulated into the same switches as the prototype.
Header to be changed to this:
/* ... as you quoted ... */
void _show_in_debug(const char *_file, unsigned int _line,
const char *_function, const char *_msg);
/* ... rest of what you quoted ... */
Code file to contain this:
#incude <stdio.h>
#include "Yourheader.h"
#ifdef NDEBUG
void _show_in_debug(const char *_file, unsigned int _line,
const char *_function, const char *_msg)
{
printf("%s\t%d\t%s\t%s\n", _file, _line, _function, _msg);
fflush(NULL);
}
#endif

I assume the file header file that you have presented is included in several source files. Why is this a problem? That is because you have defined your _show_in_debug() function in the header instead of declaring it in the header and defining it in a source file file. This leads to the function be defined in multiple source files that have included your header.
See http://www.cprogramming.com/declare_vs_define.html for more details (especially, see the "Common Cases" section).

Related

static variable in #define directive c++

Is it possible to declare static variable in a #define directive?
// header file
#define TEXT_ENUM
#ifdef TEXT_ENUM
#define TEXT_HANDLING_MACRO \
static const char * TEXT[]; \
static const char * getText( int _enum ) { \
return TEXT[_enum]; \
}
#else
#define TEXT_HANDLING_MACRO
#endif
struct Foo {
TEXT_HANDLING_MACRO
};
// cpp file
#include "foo.h"
const char * Foo::TEXT[] = {
"ONE",
"TWO",
"THREE",
0
};
How compiler will resolve static const char *, when I include this header file in some other file and try to access Foo::TEXT[].
Is it possible to declare static variable in a #define directive?
Yes, it is possible.
How compiler will resolve static const char *, when I include this header file in some other file and try to access Foo::TEXT[].
It's resolved at the linking stage.
You have to figure out what happens through the stages of compilations that the C compiler uses.
Since #define si a pre-compiler directive, everything will be resolved before actually compiling or looking at the code. Pieces of text (code, functions, whatever is included) will be passed on or filtered according to the directive.
All the rest happens after that, like compilation, that will look for global variable declaration, and linking, that will look for the address of those variable.
In you case, if you take your file and compile with a gcc compiler and the -E option (to do just the precompiler stage), you will get:
struct Foo {
static const char * TEXT[]; static const char * getText( int _enum ) { return TEXT[_enum]; }
};
const char * Foo::TEXT[] = {
"ONE",
"TWO",
"THREE",
0
};

Redefinition of custom delete

I am getting an error saying that I have redefined a function custom_delete.
header.h
#include <iostream>
#include <string>
static int unfreed_count = 0;
#define DELETE(O) custom_delete(O,__PRETTY_FUNCTION__, __LINE__)
void custom_delete(void* ptr, const std::string& function_name, unsigned int line_number) {
unfreed_count--;
std::cout << "delete called in " + function_name + ":" << line_number << std::endl;
std::cout << "unfreed_count: = " << unfreed_count << std::endl << std::endl;
free(ptr);
}
main.cpp
#include "header.h"
int main(int argc, char* argv[]) {
int* ptr = new int;
DELETE(ptr);
}
This code results in the following error message upon attempted compilation:
main.cpp: In function 'void custom_delete(void*, const string&, unsigned int)':
main.cpp:5:6: error: redefinition of 'void custom_delete(void*, const string&, unsigned int)'
void custom_delete(void* ptr, const std::string& function_name, unsigned int line_number) {
^
In file included from main.cpp:21:0:
header.h:7:6: note: 'void custom_delete(void*, const string&, unsigned int)' previously defined here
void custom_delete(void* ptr, const std::string& function_name, unsigned int line_number) {
^
I was trying to make a custom version of delete that printed out when it was used. This was in a larger project, so I made a separate project with just these two files and got the same errors.
I tried commenting out all the code inside the custom_delete function. I also tried writing the prototype before the macro. I got the same error each time.
---EDIT---
I found there was another file being compiled:
header.cpp
#include "header.h"
// Some commented out functions
If I remove the #include "header.h" everything works. However, I eventually will need to add the functions to header.cpp. These functions need stuff that will be added to header.h. What should I do?
It looks like you don't have include guard in your headers.
Add #pragma once as the first line of your header.h
or for more portable solution, add
#ifndef HEADER_H
#define HEADER_H
as first two lines, and
#endif
as last line of the header.h.
Also, to avoid link errors, add inline keyword to declaration of your function, like inline void custom_delete(...
or move function implementation to .cpp.

Redefinition of a class in a header file

I'm attempting to compile my code with g++, but its throwing this compiler error:
Enrollment.h:3:7: error: redefinition of class sict::Enrollment
Enrollment.h:3:7: error: previous definition of class sict::Enrollment
my Enrollment.h:
namespace sict{
class Enrollment{
private:
char _name[31];
char _code[11];
int _year;
int _semester;
int _slot;
bool _enrolled;
public:
Enrollment(const char* name , const char* code, int year, int semester , int time );
Enrollment();
void set(const char* , const char* , int ,int, int , bool = false );
void display(bool nameOnly = false)const;
bool valid()const;
void setEmpty();
bool isEnrolled() const;
bool hasConflict(const Enrollment &other) const;
};
}
Any way to fix this?
The problem is likely that your header file is included (directly and indirectly) in the same translation unit. You should use some way of avoiding the multiple includes of the same header file in your cpp's. I prefer #pragma once in the beginning of your header file - it is not standard but it is supported by all major compilers. Otherwise you can go for good-old include guards:
#ifndef _Enrollment_h_
#define _Enrollment_h_
// Your header contents here
#endif
or with pragma:
#pragma once
// Your header contents here
You need to use some include guards. Either #pragma once or:
#ifndef MY_FILE_H
#define MY_FILE_H
....
#endif //MY_FILE_H
This is to prevent the same code being included in every file where you include this header (double inclusion). This will essentially help out the pre-processor. More information here.

C++ link error.. is invalid?

I keep getting this Visual C++ 2010 LNK2005 linker error saying I have multiple definitions of two functions that are contained in "Error.h". (a header I made for error display)
My project is like this:
BaseImage.h
BaseImage.cpp --> includes BaseImage.h , Error.h
PNGImage.h --> includes BaseImage.h
PNGImage.cpp --> includes PNGImage.h , Error.h
main.cpp --> includes PNGImage.h
And, of course, Error.h:
/*
Optional macros:
AE_EXIT_AT_ERROR
*/
#pragma once
#include <stdexcept>
void aeError(const char *str, int code=1)
{
throw std::runtime_error(str);
#ifdef AE_EXIT_AT_ERROR
std::exit(code);
#endif
}
void aeAssert(bool b, const char *failStr = "assertion failed")
{
if(!b)
aeError(failStr);
}
I have #pragma once in every header file, and I tried adding include guards to Error.h as well.
Here's the compile output:
1>PNGImage.obj : error LNK2005: "void __cdecl aeError(char const *,int)" (?aeError##YAXPBDH#Z) already defined in BaseImage.obj
1>PNGImage.obj : error LNK2005: "void __cdecl aeAssert(bool,char const *)" (?aeAssert##YAX_NPBD#Z) already defined in BaseImage.obj
1>C:\...\Project.exe : fatal error LNK1169: one or more multiply defined symbols found
Could this be a bug?
When you define functions in a .h file, make them inline. Otherwise, the function definitions are part of the object code of all the .cpp files that #include it, with external linkage.
inline void aeError(const char *str, int code=1)
{
throw std::runtime_error(str);
#ifdef AE_EXIT_AT_ERROR
std::exit(code);
#endif
}
inline void aeAssert(bool b, const char *failStr = "assertion failed")
{
if(!b)
aeError(failStr);
}
The other option for you is to declare the functions in the .h file and define them in exactly one .cpp file.
The .h file:
extern void aeError(const char *str, int code=1);
extern void aeAssert(bool b, const char *failStr = "assertion failed");
The .cpp file:
// Don't use inline and don't include the default argument values.
void aeError(const char *str, int code)
{
throw std::runtime_error(str);
#ifdef AE_EXIT_AT_ERROR
std::exit(code);
#endif
}
void aeAssert(bool b, const char *failStr)
{
if(!b)
aeError(failStr);
}

C++ and Objective-c

i built a static library,and add the .h file to my project,
in all the class in the .h files,something like this :
class StartOp
{
static void openFiles(WavInFile **inFile, WavOutFile **outFile, const RunParameters *params);
static void setup(SoundTouch *pSoundTouch, const WavInFile *inFile, const RunParameters *params);
static void process(SoundTouch *pSoundTouch, WavInFile *inFile, WavOutFile *outFile);
static void detectBPM(WavInFile *inFile, RunParameters *params);
int start(const int nParams, const char * const paramStr[]);
};
i got this error:
StartOp.h:18: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'StartOp'
**EDIT**
i fix this problem by changing the file ex to mm.
now i want to use this code and i want to call from this class ,this code is an c++ class that i want to call him from an objective-c class:
#ifndef _STARTOP_H_
#define _STARTOP_H_
namespace soundtouch
{
class StartOp
{
static void openFiles(WavInFile **inFile, WavOutFile **outFile, const RunParameters *params);
static void setup(SoundTouch *pSoundTouch, const WavInFile *inFile, const RunParameters *params);
static void process(SoundTouch *pSoundTouch, WavInFile *inFile, WavOutFile *outFile);
static void detectBPM(WavInFile *inFile, RunParameters *params);
static int start(const int nParams, const char * const paramStr[]);
};
}
#endif
to the
static int start(const int nParams, const char * const paramStr[]);
method from my objective-c iphone app.
The code you posted is not C; it is rather C++.
Now, Objective-C and C++ can interoperate, but you need to use .mm extensions on the Objective-C side.
So if you are importing the .h. file into a .m file, you get obviously errors because the compiler is not expecting a class definition (C++). If you import the .h file into a .mm file, you have some chance that it will work (if all the rest is correct, I mean).
If you need more help, please provide more code, so that we can understand better what you are doing.