Thread: unresolved symbol

  1. #1
    Registered User
    Join Date
    Aug 2010
    Posts
    15

    unresolved symbol

    I need help to figure out why this won't link properly. I've tried defining
    VDEBUG within pellesC preprocess symbols under the project options, also
    #define VDEBUG in sllist.c and as a last resort, just removed all the
    vdebug conditionals/defines and the thing still won't link to display_list.

    sllist.h
    Code:
    #ifndef SL_LIST_H
    #define SL_LIST_H
    
    #define SL_EMEMORY 1
    
    struct sl_node {
    	void *object;
    	size_t size;
    	struct sl_node *next;	
    };
    
    struct sl_header {
    	struct sl_node *head;
    };
    
    typedef struct sl_node SL_LIST_NODE;
    typedef struct sl_header SL_LIST;
    
    SL_LIST * create_list(void);
    void destroy_list(SL_LIST *);
    int add_item(SL_LIST *, void *, size_t);
    void display_list(SL_LIST *);
    
    #endif
    sllist.c
    Code:
    #define VDEBUG
    
    #include <stddef.h>
    #include <stdlib.h>
    #include <string.h>
    
    #include "sllist.h"
    
    	
    int add_item( SL_LIST *list, void *object, size_t size ) {
    	SL_LIST_NODE *tmp = NULL;
    	void *mem = NULL;
    
    	if( (mem = malloc(size)) == NULL ) {			
    		return SL_EMEMORY;												
    	}
    
    	if( (tmp = malloc(sizeof *tmp)) == NULL ) {		
    		free(mem);		
    		return SL_EMEMORY;
    		
    	}
    
    	mem = memcpy(mem, object, size);		
    
    	tmp->next = list->head;		
    	tmp->size = size;			
    	tmp->object = mem;			
    	
    	list->head = tmp;			
    		
    	return 0;
    }
    	
    SL_LIST * create_list(void) {
    	SL_LIST *tmp;
    
    	tmp = malloc( sizeof(SL_LIST) );
    	if( tmp != NULL ) {
    		tmp->head = NULL;
    		return tmp;
    	}	
    
    	return NULL;
    }
    
    void destroy_list(SL_LIST *list) {
    	SL_LIST_NODE *tmp = NULL;
    	
    	if( list == NULL ) {
    		return;
    	}
    	
    	if( list->head != NULL ) {	
    		do {
    			tmp = list->head;				
    			free( list->head->object ); 	
    			free( list->head );				
    			list->head = tmp;	
    		} while( tmp != NULL );
    	}
    
    	free(list);							
    			
    	return;
    }
    
    #ifdef VDEBUG
    
    	#include <stdio.h>
    
    	
    void diplay_list( SL_LIST *list ) {
    	SL_LIST_NODE *tmp = NULL;
    	unsigned int i = 0;
    	unsigned int *data = NULL;
    	
    	if( list == NULL ) {
    		return;
    	}
    			
    	if( list->head != NULL ) {
    		do {
    			tmp = list->head;									
    			data = list->head->object;							
    			printf("Node: %ud\nData: %ud\n\n", i, *data);		
    			list->head = tmp;
    		} while ( tmp != NULL );					
    	}
    	return;
    }
    
    #endif
    main.c
    Code:
    /*	test driver program. */
    
    #include <stdio.h>
    #include "sllist.h"
    
    int main(void) {
    	SL_LIST *list;
    
    	if( (list = create_list()) == NULL ) {
    		printf("Failed to create list.\n");
    		return 0;
    	}
    
    	display_list(list);
    
    
    	destroy_list(list);
    
    	return 0;
    }


    PellesC warning level 2.

    Building main.obj.
    \main.c(10): warning #2216: The return value from 'printf' is never used.
    Building sllist.obj.
    \sllist.c(144): warning #2216: The return value from 'printf' is never used.
    Building testlib2.exe.
    POLINK: error: Unresolved external symbol '_display_list'.
    POLINK: fatal error: 1 unresolved external(s).
    *** Error code: 1 ***
    Done.

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    display_list is defined inside your #ifdef VDEBUG block, so if VDEBUG is not defined when you compile sllist.c, you will not have the display_list function in sllist.o for linking into your test driver program.

  3. #3
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Is sllist.c included in your current project?

    Pelles is a bit fussy about projects... it won't build anything that's not listed and then the linker will come up with undefined objects right inside your own code.

    Also note this...
    Code:
    void diplay_list( SL_LIST *list ) {
    notice anything missing?

  4. #4
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Nevermind. Take a look at the definition
    Code:
    void diplay_list( SL_LIST *list ) {  // where's the 's'?
    and the call
    Code:
        display_list(list);
    Simple spelling mistake.

  5. #5
    Registered User
    Join Date
    Aug 2010
    Posts
    15
    Good eye.

    Thanks guys, it just compiled no problem. Is there a technique to get the compiler to warn you of something like that?

  6. #6
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by deepcode View Post
    Good eye.

    Thanks guys, it just compiled no problem. Is there a technique to get the compiler to warn you of something like that?
    I think it just did....

  7. #7
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    When you have something like an unresolved symbol or unknown identifier, and you're sure you have your build settings, etc correct, it's usually something simple like a spelling mistake.

  8. #8
    Registered User
    Join Date
    Aug 2010
    Posts
    15
    Guess that's something I'll just have to remember, an experience thing?

    I was thinking along the lines of an optional flag to warn if a function has no prototype
    or something similar. This way, the compiler would say diplay_list() has no prototype, then
    I could look at it and work it out easier, over the linker telling me it can't find display_list()
    which has me thinking that something is wrong with the project/linker.

  9. #9
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Yeah, your problem came from a correctly spelled prototype and call, but incorrectly spelled definition. The option you're looking for could certainly help clear that up:
    Quote Originally Posted by man gcc
    -Wmissing-prototypes (C and Objective-C only)
    Warn if a global function is defined without a previous prototype declaration. This warning is issued even if the definition itself provides a prototype. The aim is
    to detect global functions that fail to be declared in header files.
    Looks like gcc has it. I would be surprised if Pelles doesn't have something similar. It's just a question of where to look. Tater can help you better on that.

  10. #10
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    Quote Originally Posted by deepcode View Post
    Good eye.

    Thanks guys, it just compiled no problem. Is there a technique to get the compiler to warn you of something like that?
    Intel's compiler, at -w2, and gcc with -Wmissing-declarations can flag such an error. Check your compiler's documentation to see if it provides similar warnings (i.e. find a warning about missing declarations).

    With the above-mentioned compilers, you'll see something like:
    Code:
    sllist.c:73:6: warning: no previous declaration for 'diplay_list'
    or
    sllist.c(73): remark #1418: external function definition with no prior declaration
    Such warnings will be triggered whenever you have a non-static function definition without a declaration in scope.

    Intel's compiler can also tell you when you have an external declaration in a primary source file, which helps to enforce the good practice of
    1. making functions that are used in a single file static, and
    2. providing prototypes through headers rather than manually entering them in each source file

    If your compiler provides a similar option, you might want to enable it. It will help avoid namespace pollution, which can lead to clashes. This is especially important if you're writing a library, since, apart from the public interface, you don't want to export any more symbols than are absolutely necessary.

    I wish file scope declarations had internal linkage by default, but what can you do.

  11. #11
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    The one weakness in Pelles C is that compiler errors are not thoroughly documented in the help file...
    Just about every other thing you can think of is but not this. But they're all pretty obvious anyway...

    There's always my favorite: "More than 100 errors, please improve yourself"... Absolutely hilarious!

    For deepcode's problem... when you see linker messages like that you need to check any place the function is named... definition, prototypes, calls etc... as anduril points out, when there's only one of them, it's almost always a spelling error. When there are multiples it's most often that the linker can't find the .lib to pull from... and that can usually be fixed in project -> project options -> folders -> libraries.

  12. #12
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by cas View Post
    Intel's compiler, at -w2, and gcc with -Wmissing-declarations can flag such an error. Check your compiler's documentation to see if it provides similar warnings (i.e. find a warning about missing declarations).
    Yes, thank you, but he's not using either of those.

    deepcode is using a REAL compiler

  13. #13
    Registered User
    Join Date
    Aug 2010
    Posts
    15
    Thanks, I'll read the help docs in Pelles after work and see what it has available

  14. #14
    Registered User
    Join Date
    Aug 2010
    Posts
    15
    Had some issues with the first version that annoyed me, so I rebuilt it with the ideas and techniques I already had. Seems to work just fine, there are some other functions that I'd like to add in the future, such as adding different lists together, or adding an item to a specific point in the list. But I can always improve it peicemeal.

    Next I'm gonna build some other data things, such as a stack, on top of this and go from there :P

    Any feedback of design, technique would be good. ( pasting this over from the source is telling me to stop using tabs and change to spaces )

    header:
    Code:
    /*	sllist.h
    
    	may 4/2011
    	deepcode
    	version 2.0
    
    	header for sllist version 2. */
    
    #ifndef SL_LIST_H
    #define SL_LIST_H
    
    #define SL_SUCCESS 0
    #define SL_ERROR -1
    
    struct sl_node {
    	void *object;
    	size_t size;
    	struct sl_node *next;	
    };
    
    struct sl_header {
    	struct sl_node *head;
    	struct sl_node *tail;
    };
    
    struct sl_memory {
    	unsigned long int header_memory;
    	unsigned long int data_memory;
    };
    
    typedef struct sl_node SL_LIST_NODE;
    typedef struct sl_header SL_LIST;
    typedef struct sl_memory SL_MEMORY;
    
    int sl_create_list ( SL_LIST ** );
    int sl_destroy_list ( SL_LIST ** );
    void sl_display_list ( const SL_LIST *list );
    int sl_add_head ( SL_LIST *, const void *, const size_t );
    int sl_add_tail ( SL_LIST *, const void *, const size_t );
    int sl_count_items ( const SL_LIST * );
    void * sl_get_item ( const SL_LIST *, int );
    int sl_update_item ( const SL_LIST *, int, void *, size_t );
    int sl_remove_item ( SL_LIST *, int );
    int sl_get_mem ( const SL_LIST *, SL_MEMORY * );
    
    #endif
    source
    Code:
    /*	sllist.c
    
    	may 4/2011
    	deepcode
    	version 2.0
    
    	Module for management of single linked lists. */
    
    #include <stddef.h>
    #include <stdlib.h>
    #include <string.h>
    #include "sllist.h"
    
    #ifdef VDEBUG
    	#include <stdio.h>
    #endif
    
    int sl_get_mem ( const SL_LIST *list, SL_MEMORY *mem ) {
    	SL_LIST_NODE *tmp;
    
    	if( list != NULL ) {
    		if( mem != NULL ) {
    			mem->header_memory = 0;
    			mem->data_memory = 0;
    			if( list->head != NULL ) {
    				mem->header_memory += sizeof *list;
    				tmp = list->head;
    				do {
    					mem->header_memory += sizeof *tmp;
    					mem->data_memory += tmp->size;
    					tmp = tmp->next; 
    				} while ( tmp != NULL );
    				return SL_SUCCESS;
    			}	
    			mem->header_memory += sizeof *list;	
    			mem->data_memory = 0;
    			return SL_SUCCESS;
    		}
    	}
    	return SL_ERROR;
    }
    
    	/* Finished. */
    int sl_remove_item ( SL_LIST *list, int node ) {
    	SL_LIST_NODE *tmp = NULL;
    	SL_LIST_NODE *front = NULL;
    	SL_LIST_NODE *back = NULL;
    	int record = 1;
    
    	if( node > 0) {
    		if( list != NULL ) {
    			if( list->head != NULL ) {
    				tmp = list->head;				
    				if( node == 1 ) {				
    					if( tmp->next == NULL ) { 	
    						free( tmp->object );
    						free( tmp );
    						list->head = NULL;		
    						list->tail = NULL;		
    						return SL_SUCCESS;		
    					}
    					back = tmp->next;			
    					free( tmp->object );
    					free( tmp );
    					list->head = back;			
    					return SL_SUCCESS;			
    				}
    				do {	
    					if( record == ( node - 1 ) ) {			
    						front = tmp;				
    						if( tmp->next == NULL ) {	
    							return SL_ERROR;
    						}
    						tmp = tmp->next;			
    						if( tmp->next == NULL ) {	
    							front->next = NULL;		
    							list->tail = front;		
    							free( tmp->object );	
    							free( tmp );	
    							return SL_SUCCESS;		
    						}
    						back = tmp->next;			
    						front->next = back;			
    						free ( tmp->object );
    						free ( tmp );
    						return SL_SUCCESS;			
    					}
    					tmp = tmp->next;						
    					record++;								
    				} while ( tmp != NULL );
    			}	
    		}
    	}
    	return SL_ERROR;
    }
    
    	/* Finished. */
    int sl_update_item ( const SL_LIST *list, int node, void *object, size_t size) {
    	SL_LIST_NODE *tmp = NULL;
    	void *mem = NULL;
    	int record = 1;
    
    	if( node > 0 ) {
    		if( list != NULL ) {
    			if ( list->head != NULL ) {
    				tmp = list->head;
    				while( tmp != NULL ) {
    					if( record == node ) {
    						if( (mem = realloc(tmp->object, size)) != NULL) {
    							mem = memcpy(mem, object, size);
    							tmp->object = mem;
    							tmp->size = size;
    							return SL_SUCCESS;
    						}
    						break;	
    					}
    					record++;
    					tmp = tmp->next;
    				}
    			}
    		}
    	}
    	return SL_ERROR;
    }
    
    	/* Finished */
    void * sl_get_item ( const SL_LIST *list, int node ) {
    	SL_LIST_NODE *tmp;
    	int record = 0;
    
    	if( node > 0 ) {
    		if( list != NULL ) {
    			if( list->head != NULL ) {
    				tmp = list->head;
    				do {
    					record++;
    					if( record == node ) {
    						return tmp->object;
    					}
    					tmp = tmp->next;
    				} while( tmp != NULL );
    			}
    		}
    	}
    	return NULL;
    }
    
    	/* Finished. */
    int sl_count_items ( const SL_LIST *list ) {
    	SL_LIST_NODE *tmp = NULL;
    	int records = 1;
    
    	if( list != NULL ) {
    		if( list->head != NULL ) {
    			tmp = list->head;
    			while( tmp->next != NULL ) {
    				records++;
    				tmp = tmp->next;
    			}
    			return records;
    		}
    		return 0;
    	}
    	return SL_ERROR;
    }
    
    	/* Finished */
    int sl_add_tail ( SL_LIST *list, const void *object, const size_t size ) {
    	SL_LIST_NODE *tmp = NULL;
    	void *mem = NULL;
    
    	if( list != NULL ) {
    		if( (mem = malloc(size)) != NULL ) {
    			if( (tmp = malloc(sizeof *tmp)) != NULL ) {
    				mem = memcpy(mem, object, size);
    				tmp->next = NULL;
    				tmp->size = size;
    				tmp->object = mem;
    				if( list->tail != NULL ) {
    					list->tail->next = tmp;
    				}
    				list->tail = tmp;
    				return SL_SUCCESS;
    			}
    			free(mem);
    		}
    	}
    	return SL_ERROR;
    }
    
    	/* Finished. */
    int sl_add_head ( SL_LIST *list, const void *object, const size_t size ) {
    	SL_LIST_NODE *tmp = NULL;
    	void *mem = NULL;
    
    	if( list != NULL ) {
    		if( (mem = malloc(size)) != NULL ) {
    			if( (tmp = malloc(sizeof *tmp)) != NULL ) {
    				mem = memcpy(mem, object, size);
    				tmp->next = list->head;		
    				tmp->size = size;			
    				tmp->object = mem;
    				list->head = tmp;
    				if( list->tail == NULL ) {
    					list->tail = tmp;
    				}
    				return SL_SUCCESS;
    			}
    			free(mem);
    		}
    	}
    	return SL_ERROR;
    }
    
    	/* Finished. */
    int sl_create_list ( SL_LIST **list ) {
    	SL_LIST *tmp = NULL;
    
    	if( *list == NULL ) {
    		tmp = malloc( sizeof(SL_LIST) );
    		if( tmp != NULL ) {
    			tmp->head = NULL;
    			tmp->tail = NULL;
    			*list = tmp;
    			return SL_SUCCESS;
    		}
    	}	
    	return SL_ERROR;
    }
    
    	/* Finished */
    int sl_destroy_list ( SL_LIST **list ) {
    	SL_LIST_NODE *tmp = NULL;
    
    	if( *list != NULL ) {
    		if( (*list)->head != NULL ) {
    			do {
    				tmp = (*list)->head->next;			
    				free( (*list)->head->object );
    				free( (*list)->head );
    				(*list)->head = tmp;
    			} while( tmp != NULL );			
    		}
    		free( *list );
    		*list = NULL;
    		return SL_SUCCESS;
    	}
    	return SL_ERROR;	
    }
    
    #ifdef VDEBUG
    
    	/* Finished. */
    void sl_display_list( const SL_LIST *list ) {
    	SL_LIST_NODE *tmp = NULL;
    	SL_LIST_NODE *tmphead = NULL;
    	unsigned char *data = NULL;
    	unsigned int records = 0;
    	size_t size = 0;			
    				
    	if( list != NULL ) {
    		tmphead = list->head;
    		if( list->head != NULL ) {
    			records++;
    			do {
    				tmp = tmphead->next;								
    				data = tmphead->object;	
    				printf("Node: %d\n", records);
    				for( size = tmphead->size ; size > 0 ; size-- ) {
    					printf("%c", *data);
    					data++;
    				}
    				printf("\n");
    				records++;
    				tmphead = tmp;		
    			} while ( tmp != NULL );
    			return;					
    		}
    		printf("No nodes in the list.\n");
    		return;
    	}
    	printf("No list.\n");
    }
    
    #endif

  15. #15
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by deepcode View Post
    Thanks, I'll read the help docs in Pelles after work and see what it has available
    If only I had a penny for every time I've told people to read help files....

    Pelles C has the best help file I've ever seen... put your typing cursor on any keyword and press F1...

    ( pasting this over from the source is telling me to stop using tabs and change to spaces )
    Best setup ... Tools -> Options -> Tabs...
    Tab size = 2;
    Indent size = 2;
    Insert spaces = checked
    AutoIndent = Block
    C Formatting style = style 2

    Produces really nice code...
    Last edited by CommonTater; 05-05-2011 at 06:00 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. unresolved symbol -_- (static int)
    By Lynux-Penguin in forum C++ Programming
    Replies: 3
    Last Post: 10-11-2003, 06:23 PM
  2. PlaySound unresolved symbol
    By curlious in forum Windows Programming
    Replies: 4
    Last Post: 10-04-2003, 03:29 PM
  3. unresolved external symbol
    By gazsux in forum C++ Programming
    Replies: 12
    Last Post: 01-09-2003, 05:05 PM
  4. unresolved external symbol
    By scuba22 in forum C++ Programming
    Replies: 2
    Last Post: 10-22-2002, 04:00 PM
  5. unresolved external symbol
    By dana_h in forum C Programming
    Replies: 3
    Last Post: 05-09-2002, 02:14 AM