When syntax errors arent enough

Started by
9 comments, last by Zahlman 19 years, 6 months ago
Ok, so here I finally get to this point in my life that I can write pretty much syntax error free code, so I'm like, ‘that’s cool, now I can do anything’ well, just as things were looking up, here comes Link errors, to wreck my party. So long story short, I'm writing a 2D battle tank game, (the one were you aim, set bullet force, etc. sorta like worms) in C++ using SDL. Anyway, I'm on VC++ 6 and my code is in 4 parts: Helper.cpp Pixelwar.cpp Terrain.cpp Pixelwar.h I’ll give you the includes/declarations of the files: helper.cpp

#include "sdl.h"
#include <iostream>
#include <memory.h>

Pixelwar.cpp

#include "sdl.h"
#include <iostream>
#include <ctime>
#include <cmath>
#include <windows.h>
#include "pixelwar.h"
#include "helper.cpp"
#include "terrain.cpp"


// Functions
int init();
int frame();

//Variables
SDL_Surface* screen;
SDL_Event event;
Uint8* keys;
SDL_Color k;

cTerrain terrain;

terrain.cpp

#include "sdl.h"
#include <iostream>
#include <cmath>
#include "pixelwar.h"



class cTerrain {
public:	
	void InitTerrain(SDL_Color k);
	void PixelOn(int x, int y);
	void PixelOff(int x, int y);
	void SetColor(SDL_Color k);
	SDL_Color GetColor();
	void draw(SDL_Surface* screen);
private:
	bool PixArray[SCREEN_WIDTH][SCREEN_HEIGHT];
	SDL_Color drawcolor;
};

void cTerrain::InitTerrain(SDL_Color k) {
	int highY = 0;
	for (int x = 0; x < SCREEN_WIDTH; x++) {
		highY = ((rand() % SCREEN_HEIGHT) * -1) + SCREEN_HEIGHT;
		for (int y = SCREEN_HEIGHT; y > 0; y--){
			if (y > highY) PixArray[x][y] = true;
			else PixArray[x][y] = false;
		}
	}
	drawcolor = k;
}

pixelwar.h (whole file)

#include "sdl.h"
#include <iostream>


#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
#define SCREEN_BPP 32

#ifndef _pixelwar_h_
#define _pixelwar_h_ 1
void SetPixel(SDL_Surface *screen, int x, int y, Uint8 r, Uint8 g, Uint8 b);
SDL_Color GetPixel ( SDL_Surface* pSurface , int x , int y );
SDL_Color SDL_MakeColor (int r, int g, int b);

#endif

ok, so thats the files, heres the errors --------------------Configuration: pixelwar - Win32 Debug-------------------- Compiling... pixelwar.cpp Linking... pixelwar.obj : error LNK2005: "void __cdecl SetPixel(struct SDL_Surface *,int,int,unsigned char,unsigned char,unsigned char)" (?SetPixel@@YAXPAUSDL_Surface@@HHEEE@Z) already defined in helper.obj pixelwar.obj : error LNK2005: "struct SDL_Color __cdecl GetPixel(struct SDL_Surface *,int,int)" (?GetPixel@@YA?AUSDL_Color@@PAUSDL_Surface@@HH@Z) already defined in helper.obj pixelwar.obj : error LNK2005: "struct SDL_Color __cdecl SDL_MakeColor(int,int,int)" (?SDL_MakeColor@@YA?AUSDL_Color@@HHH@Z) already defined in helper.obj terrain.obj : error LNK2005: "public: void __thiscall cTerrain::InitTerrain(struct SDL_Color)" (?InitTerrain@cTerrain@@QAEXUSDL_Color@@@Z) already defined in pixelwar.obj terrain.obj : error LNK2005: "public: void __thiscall cTerrain::PixelOn(int,int)" (?PixelOn@cTerrain@@QAEXHH@Z) already defined in pixelwar.obj terrain.obj : error LNK2005: "public: void __thiscall cTerrain::PixelOff(int,int)" (?PixelOff@cTerrain@@QAEXHH@Z) already defined in pixelwar.obj terrain.obj : error LNK2005: "public: void __thiscall cTerrain::SetColor(struct SDL_Color)" (?SetColor@cTerrain@@QAEXUSDL_Color@@@Z) already defined in pixelwar.obj terrain.obj : error LNK2005: "public: struct SDL_Color __thiscall cTerrain::GetColor(void)" (?GetColor@cTerrain@@QAE?AUSDL_Color@@XZ) already defined in pixelwar.obj terrain.obj : error LNK2005: "public: void __thiscall cTerrain::draw(struct SDL_Surface *)" (?draw@cTerrain@@QAEXPAUSDL_Surface@@@Z) already defined in pixelwar.obj MSVCRTD.lib(cinitexe.obj) : warning LNK4098: defaultlib "msvcrt.lib" conflicts with use of other libs; use /NODEFAULTLIB:library Debug/pixelwar.exe : fatal error LNK1169: one or more multiply defined symbols found Error executing link.exe. Creating browse info file... pixelwar.exe - 10 error(s), 1 warning(s) mmmmk, im sorry all the stuff, but im confused, ive read some stuff about splitting files apart etc. but this one has me stumped thanks in advance -- Jake
Advertisement
If you are using VC++ 6.0 then you should change the Code Generation in C/C++ tab from Debug Single Threaded to Debug Multithreaded DLL.

If you have already done that then I am not sure why you are getting these errors.

For other compilers I suggest you read the Docs that come with SDL.
The more applications I write, more I find out how less I know
You should only ever #include headers (.h, .hpp), never source files (.c, .cc, .cpp). The problem is that you define the same function more than once because each .cpp file (by virtue of being included and compiled by itself) gets compiled multiple times.
I just want to give up and die when I get these. The only solution I have found so far is to not include the files and try rearranging the code in all of the files and just hope things work...
So I'm very interested in how to solve this problem.
____________________________________________________________Programmers Resource Central
yeah man, does anyone know of a really good tutorial on beating these things, i found one once, but i cant find it any more
Kylotan wrote a guide. The important thing, however, is keeping in mind that you must define everything that you use once—and only once. This is why you only place declarations in headers (it doesn't matter how many times you declare symbols), never definitions; definitions go in source files, which shall never be compiled more than once (that is, no two object files should ever contain the same source file, and you should never ever #include a source file).
Never include a file which includes a variable definition or a non-inline function definition. Otherwise, the compiler will dutifully create multiple copies of those functions and variable, and the linker will get confused over which to pick (the fact that they are code-identical is inconsequential, the linker only sees multiple symbols with the same name). For things like classes and inline functions, which can be multiply defined across multiple translations units (cpp files + every thing they #include), the definitions must be identical (otherwise Bad Things™ happen).

A header file should only include declarations (learn to use the extern keyword[attention]), constants and enums, templates, class definitions (including struct, union...) and inline functions.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
People don't read documentation or try to understand processes. Fortunately, technology is gradually obviating the need for such diligence.

In C (and therefore in C++), all entities must be declared before they are referenced, and then defined only once for a given scope. Traditionally, declarations are placed in header files (.h, .hpp, .hxx) while definitions are placed in implementation files (.c, .cpp, .cxx, .cc). If an entity is defined twice within a given scope, you get a redefinition error, which is shade13's problem. We conventionally don't include implementation files because they get compiled on their own if they're part of the project workspace.

It is important to clearly understand the difference between a declaration and a definition. int i; is a definition without initialization; extern int i; is a declaration, and it requires that there still be a definition - and only one definition. For functions, the process is simplified and doesn't require the use of the extern keyword: int function(void); is a declaration; replace the statement terminator (;) with a statement block to yield a definition.

Don't know what a statement block is? Look it up. I'm not going to teach you everything, after all!
Yay, i think i fixed it.
for the sake of anyone else confused, i read that guide miserable recomended, then i made a new header file for helper.cpp, called helper.h, then i put all the 'helper' function declerations into it, it seems to be working, cause now i just include that one wherever i need

--Jake
Quote:Robert Martin
About two years ago I noticed something. I was depending less and less on the type system for safety. My unit tests were preventing me from making type errors. The more I depended upon the unit tests, the less I depended upon the type safety of Java or C++ (my languages of choice).

I thought an experiment was in order. So I tried writing some applications in Python, and then Ruby (well known dynamically typed languages). I was not entirely surprised when I found that type issues simply never arose. My unit tests kept my code on the straight and narrow. I simply didn't need the static type checking that I had depended upon for so many years.

Quote:Bruce Eckel
Robert came to more or less the same conclusion I have, but he did so by becoming "test infected" first, then realizing that the compiler was just one (incomplete) form of testing, then understanding that a weakly-typed language could be much more productive but create programs that are just as robust as those written in strongly-typed languages, by providing adequate testing.

Of course, Martin also recieved the usual "how can you possibly think this?" comments. Which is the very question that lead me to begin struggling with the strong/weak typing concepts in the first place. And certainly both of us began as strong static type checking advocates. It's interesting that it takes an earth-shaking experience — like becoming test-infected or learning a different kind of language — to cause a re-evaluation of beliefs.

This topic is closed to new replies.

Advertisement