C++ Undefined Reference Issues

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
enigma
Posts: 18
Joined: Tue Dec 25, 2007 10:52 am

C++ Undefined Reference Issues

Post by enigma »

Hi, I just switched over to C++ recently, and I'm having some issues with my code.

I wrote a class, k_video split between a .hpp and a .cpp file. It compiles just fine, but when I try to link it into the kernel, I get tons of undefined references. I tried changing the linking order, but to no avail. Can anyone help?

I'm running Arch linux with a 4.4.3 GCC cross compiler setup.

video.hpp:

Code: Select all

#ifndef __VIDEO_HPP
#define __VIDEO_HPP

namespace kernel
{

class k_screen
{
	public:
		k_screen(void *, unsigned short, unsigned short);
		k_screen();

		void clear();
		k_screen &operator<<(char const * str);
		// Print a single character to screen.
		k_screen &operator<<(char const c);
		// Print a character value to screen
		k_screen &operator<<(unsigned char const c);
		// Print a signed integer to screen.
		k_screen &operator<<(signed long integer);
		// Print an unsigned integer to screen.
		k_screen &operator<<(unsigned long integer);
		// Print an address to screen. (Automatically 'hex' mode.)
		k_screen &operator<<(void * ptr);
		k_screen &operator<<(void (*formatter)());
		static void putc(char const c);
		static void setBase(unsigned char const bass);
	private:
		k_screen(k_screen&);
		k_screen& operator=(k_screen const &);
		
		// Print a null-terminated string to screen. CR/LF at end of string.
		// @param ptr Pointer to the string to be printed.
		void write(char const * ptr);
		
		// Column Number
		static unsigned char csr_x;
		static unsigned char csr_y;
		static unsigned char color;
		static unsigned char base;
		static unsigned short height;
		static unsigned short width;
		static unsigned short *mem_addr;
};

extern void endl();
extern void hex();
extern void dec();

}
#endif
video.cpp:

Code: Select all

#include <video.hpp>

namespace kernel
{

k_screen::k_screen(void *addr, unsigned short ht, unsigned short wd)
{
	mem_addr = reinterpret_cast<unsigned short *>(addr);
	height = ht;
	width = wd;
	color = 0x0F;
	csr_x = 0;
	csr_y = 0;
}

void k_screen::clear()
{
	for(int i = 0; i < width * height; i++)
	{
		mem_addr[i] = ' ' | (color << 8);
	}
	csr_x = 0;
	csr_y = 0;
}

k_screen &k_screen::operator << (const char *str)
{
	write(str);
	return *this;
}

k_screen &k_screen::operator << (const char c)
{
	putc(c);
	return *this;
}

k_screen &k_screen::operator << (const unsigned char c)
{
	unsigned char tmp_base = base;
	base = 16;
	operator<<(static_cast<unsigned long>(c));
	base = tmp_base;
	return *this;
}

k_screen &k_screen::operator << (long integer)
{
	unsigned long new_int;
	if (integer < 0)
	{
		putc('-');
		new_int = integer * -1;
	}
	else
	{
		new_int = integer;
	}
	return operator<<(new_int);
}

k_screen &k_screen::operator<<(unsigned long integer)
{
	// prepare C string buffer (array)
	char buf[40];           // enough for 2^128 in decimal notation!
	char* idx = buf;        // pointer into the array
	// "slice off" digits from the back with the modulo operator
	do
	{
		unsigned char digit = integer % base;
		if (digit < 10)
		{
			*idx++ = '0' + digit;
		}
		else
		{
			*idx++ = 'A' + (digit - 10);
		}
	} while ((integer /= base) > 0);
	// for hex output, add leading zeroes to "round" length to power of 2,
	// and "0x" to declare hexadecimal base.
	if (base == 16)
	{
		while ((idx - buf) < 8) // 32 bit - 8 hex digits
		{
			*idx++ = '0';
		}
		*idx++ = 'x';
		*idx++ = '0';
	}
	if (base == 2)
	{
		while ((idx - buf) < 32) // 32 bit - 32 binary digits
		{
			*idx++ = '0';
		}
		*idx++ = 'b';
	}
	// reverse everything between buf and idx
	char * begidx = buf;     // first unreversed character
	char * endidx = idx - 1; // last unreversed character
	while (begidx < endidx)
	{
		// exchange characters, move indexes
		char tmp = *endidx;
		*endidx-- = *begidx;
		*begidx++ = tmp;
	}
	*idx++ = 0; // terminate string
	write(buf); // write string
	return *this;
}

k_screen &k_screen::operator<<(void * ptr)
{
	// store adress as number in an integer
	unsigned long address = reinterpret_cast<unsigned long>(ptr);
	// adresses always in hexadecimal notation
	unsigned char tmp_base = base;
	base = 16;
	operator<<(static_cast<unsigned long>(address));
	base = tmp_base;
	return *this;
}

k_screen &k_screen::operator<<(void (*formatter)())
{
	// execute the formatter function
	formatter();
	return *this;
}

void k_screen::putc(const char c)
{
	switch (c)
	{
		case '\n':
			csr_x = width;
			break;
		case '\t':
			csr_x += 7 - (csr_x % 8);
			break;
		default:
			mem_addr[((csr_y * width + csr_x) * 2)] = (c | (color << 8));
			break;
	}
	if (csr_x == width)
	{
		csr_x = 0;
		csr_y++;
	}
	if (csr_y * width >= height * width)
	{
		unsigned short* dest_ptr = mem_addr;
		unsigned short* src_ptr  = mem_addr + width;
		while (src_ptr < (mem_addr + height * width))
		{
			// copy characters one line up
			*dest_ptr++ = *src_ptr++;
		}
		while (dest_ptr < (mem_addr + height * width))
		{
			// fill last line with spaces
			*dest_ptr++ = ' ' | color << 8;
		}
		csr_y--;
	}
}

void k_screen::setBase(const unsigned char bass)
{
	base = bass;
}

void endl()
{
	k_screen::putc('\n');
}


void hex()
{
	k_screen::setBase(16);
}


void dec()
{
	k_screen::setBase(10);
}

void k_screen::write(char const * ptr)
{
	while (*ptr != '\0')
	{
		putc(*ptr++);
	}
}

}
And finally, the error messages:

Code: Select all

[me@myhost Pri]$ make                                                               
src/video.o: In function `kernel::k_screen::k_screen(void*, unsigned short, unsigned short)':
/video.cpp:8: undefined reference to `kernel::k_screen::mem_addr'
/video.cpp:9: undefined reference to `kernel::k_screen::height'  
/video.cpp:10: undefined reference to `kernel::k_screen::width'  
/video.cpp:11: undefined reference to `kernel::k_screen::color'  
/video.cpp:12: undefined reference to `kernel::k_screen::csr_x'  
/video.cpp:13: undefined reference to `kernel::k_screen::csr_y'  
src/video.o: In function `kernel::k_screen::k_screen(void*, unsigned short, unsigned short)':
/video.cpp:8: undefined reference to `kernel::k_screen::mem_addr'
/video.cpp:9: undefined reference to `kernel::k_screen::height'  
/video.cpp:10: undefined reference to `kernel::k_screen::width'  
/video.cpp:11: undefined reference to `kernel::k_screen::color'  
/video.cpp:12: undefined reference to `kernel::k_screen::csr_x'  
/video.cpp:13: undefined reference to `kernel::k_screen::csr_y'  
src/video.o: In function `kernel::k_screen::clear()':                                        
/video.cpp:20: undefined reference to `kernel::k_screen::mem_addr'
/video.cpp:20: undefined reference to `kernel::k_screen::color'   
/video.cpp:18: undefined reference to `kernel::k_screen::width'   
/video.cpp:18: undefined reference to `kernel::k_screen::height'  
/video.cpp:22: undefined reference to `kernel::k_screen::csr_x'   
/video.cpp:23: undefined reference to `kernel::k_screen::csr_y'   
src/video.o: In function `kernel::k_screen::operator<<(unsigned char)':                       
/video.cpp:40: undefined reference to `kernel::k_screen::base'    
/video.cpp:41: undefined reference to `kernel::k_screen::base'    
/video.cpp:43: undefined reference to `kernel::k_screen::base'    
src/video.o: In function `kernel::k_screen::operator<<(unsigned long)':                       
/video.cpp:70: undefined reference to `kernel::k_screen::base'    
/video.cpp:68: undefined reference to `kernel::k_screen::base'    
src/video.o:/src/video.cpp:82: more undefined references to `kernel::k_screen::base' follow
src/video.o: In function `kernel::k_screen::putc(char)':                                                           
/video.cpp:138: undefined reference to `kernel::k_screen::width'                       
/video.cpp:138: undefined reference to `kernel::k_screen::csr_x'                       
/video.cpp:141: undefined reference to `kernel::k_screen::csr_x'                       
/video.cpp:141: undefined reference to `kernel::k_screen::csr_x'                       
/video.cpp:141: undefined reference to `kernel::k_screen::csr_x'                       
/video.cpp:144: undefined reference to `kernel::k_screen::mem_addr'                    
/video.cpp:144: undefined reference to `kernel::k_screen::csr_y'                       
/video.cpp:144: undefined reference to `kernel::k_screen::width'                       
/video.cpp:144: undefined reference to `kernel::k_screen::csr_x'
/video.cpp:144: undefined reference to `kernel::k_screen::color'
/video.cpp:147: undefined reference to `kernel::k_screen::csr_x'
/video.cpp:147: undefined reference to `kernel::k_screen::width'
/video.cpp:149: undefined reference to `kernel::k_screen::csr_x'
/video.cpp:150: undefined reference to `kernel::k_screen::csr_y'
/video.cpp:150: undefined reference to `kernel::k_screen::csr_y'
/video.cpp:152: undefined reference to `kernel::k_screen::csr_y'
/video.cpp:152: undefined reference to `kernel::k_screen::width'
/video.cpp:152: undefined reference to `kernel::k_screen::height'
/video.cpp:152: undefined reference to `kernel::k_screen::width'
/video.cpp:154: undefined reference to `kernel::k_screen::mem_addr'
/video.cpp:155: undefined reference to `kernel::k_screen::mem_addr'
/video.cpp:155: undefined reference to `kernel::k_screen::width'
/video.cpp:156: undefined reference to `kernel::k_screen::mem_addr'
/video.cpp:156: undefined reference to `kernel::k_screen::height'
/video.cpp:156: undefined reference to `kernel::k_screen::width'
/video.cpp:164: undefined reference to `kernel::k_screen::color'
/video.cpp:161: undefined reference to `kernel::k_screen::mem_addr'
/video.cpp:161: undefined reference to `kernel::k_screen::height'
/video.cpp:161: undefined reference to `kernel::k_screen::width'
/video.cpp:166: undefined reference to `kernel::k_screen::csr_y'
/video.cpp:166: undefined reference to `kernel::k_screen::csr_y'
src/video.o: In function `kernel::k_screen::setBase(unsigned char)':
/video.cpp:172: undefined reference to `kernel::k_screen::base'
make: *** [pri.bin] Error 1
Any ideas?
gedd
Member
Member
Posts: 104
Joined: Thu Apr 10, 2008 1:47 am

Re: C++ Undefined Reference Issues

Post by gedd »

C++ issue

Code: Select all

    
 // Column Number
      static unsigned char csr_x;
      static unsigned char csr_y;
      static unsigned char color;
      static unsigned char base;
      static unsigned short height;
      static unsigned short width;
      static unsigned short *mem_addr;
static from your hpp must be define in your cpp

Code: Select all

  unsigned char k_screen:: csr_x;
      unsigned char k_screen::csr_y;
      unsigned char k_screen::color;
      unsigned char k_screen::base;
      unsigned short k_screen::height;
      unsigned short k_screen::width;
      unsigned short *k_screen::mem_addr;
[ Grub 2 | Visual Studio 2013 | PE File ]
The OsDev E.T.
Don't send OsDev MIB !
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Re: C++ Undefined Reference Issues

Post by pcmattman »

Hmm, do you actually understand the static keyword when applied to class members?

You'll probably also want code to call global constructors, if you haven't written that already.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: C++ Undefined Reference Issues

Post by Combuster »

You are also missing two defined but not implemented constructors. For pendancy, you are also missing the definition and implementation of the destructor. To prevent duplicate symbols, some required class components are only generated when it sees the implementation of a certain function - which is the destructor by default, but it will use something else when there is none defined.

On another note, learning a language as part of OS development is generally considered a Bad Idea(tm).
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Post Reply