"Undefined symbol <function> first referenced in file <file>" link error - c

I'm writing my first program in C for a class; I've managed to even out most of the syntax errors, but I'm getting a strange error when gcc tries to link the object files together. It prints exactly like below:
gcc -o proj04.support.o proj04.driver.o
Undefined first referenced
symbol in file
convert proj04.driver.o
I've looked around for a few answers, but none really make sense to me. I'll post the files I'm using to make the program below, and if you've got the answer I would really appreciate the help. It seems to be a pretty basic error, so it's probably something silly I didn't do.
Makefile (posting this first because I suspect the issue is here)
# Comments
# Comments
proj04: proj04.support.o proj04.driver.o
gcc -o proj04.support.o proj04.driver.o
proj04.support.o: proj04.support.c
gcc -Wall -c proj04.support.c
proj04.driver.o: proj04.driver.c
gcc -Wall -c proj04.driver.c
Header file (provided by the professor, unchangeable, one line long):
int convert( int, unsigned, char[], int )
Implementation file
#include <stdio.h>
#include "/user/cse320/Projects/project04.support.h"
#include <string.h>
void formatdisplay( char[], int );
int convert( int I, unsigned base, char result[], int display )
{
int quotient, dividend, remainder;
const int divisor = base;
int count = 0;
char ending[] = " base ";
dividend = I;
remainder = 0;
quotient = 1;
while (quotient != 0)
{
if (count <= strlen(result))
{
quotient = (dividend / divisor);
remainder = (dividend % divisor);
//convert to ascii char
result[count] = remainder;
count++;
}
}
formatdisplay ( result, display );
strrev(result);
if ( I >= 0 ) { result[0] = '+'; }
if ( I < 0 ) { result[0] = '-'; }
printf( "%s" , strcat (result, ending));
}
void formatdisplay ( char str[], int disp )
{
if ( disp < 0 )
{
unsigned i = 0;
for ( i; i < strlen(str)-1; i++)
{
if ( str[i] = '\0') { str[i] = '0'; }
}
}
if ( disp >= 0 )
{
unsigned i = 0;
for ( i; i < strlen(str)-1; i++)
{
if ( str[i] = '\0') { str[i] = ' '; }
}
}
}
Driver file (not really implemented yet)
#include <stdio.h>
#include "/user/cse320/Projects/project04.support.h"
int main () {
char Result1[32];
int T = convert(10, 2, Result1, 1);
}

Yes, the problem is probably in the Makefile:
proj04: proj04.support.o proj04.driver.o
gcc -o proj04.support.o proj04.driver.o
The -o option to gcc takes an argument, the output filename. So this is asking gcc to link the file proj04.driver.o, producing an output file of proj04.support.o.
gcc -o proj04 proj04.support.o proj04.driver.o should work better.

I had the almost the same problem.
Undefined first referenced symbol in file isThreeOfAKind /var/tmp//ccIQWbaj.o
My problem was that I had missed on a letter in one of my functions, so the declaration and the function misaligned. Ex:
void isThreeOfAKind (void);
void isThreeOfAkind {}
Missed the uppercase K, and wrote lowercase k instead.
After I changed the k to a uppercase K it compiled fine.
I dont know if it helps, but it could be something as easy as that.

I am no expert but as Andreas Joensson (who, judging by function name is writing the exact same program I am) says above this problem seems to occur when there's some mismatch between declaration and use of a function.
Your function convert is declared as returning an int but I find no return value. That might be the problem.

Related

Optimized method to check if an integer lies in the given range/bounds check

In c programming to find if any given value lies between the range, if condition is used as below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define U_LIMIT 100
#define L_LIMIT -100
int check_num(char *in)
{
int i = 0;
if (in[i] == '-' || in[i] == '+') {
i++;
if (in[i] == '\0')
return 0;
}
while (i < strlen(in)) {
if(!isdigit(in[i]))
return 0;
i++;
}
return 1;
}
int main(int argc, char *argv[])
{
int i;
if (argc != 2)
return 1;
if (!check_num(argv[1])) {
printf("Not a digit\n");
return 1;
}
i = atoi(argv[1]);
if (i < U_LIMIT && i > L_LIMIT)
printf("Within Range\n");
else
printf("Outside Range\n");
return 0;
}
Sample Output:
./a.out 1 -> Within Range
./a.out 100 -> Outside Range
./a.out -100 -> Outside Range
./a.out - -> Not a digit
./a.out e -> Not a digit
My question is that
Can the above program be optimized(for speed) further without loosing out any of the error check conditions?
Is there any other best optimized(for speed) method to solve for the same issue?
There's no need to check the user input, and then parse it. Just use sscanf to accomplish both at once:
#include <stdio.h>
#define U_LIMIT 100
#define L_LIMIT -100
int main(int argc, char *argv[])
{
int i;
if (argc != 2) {
printf("Missing argument\n");
return 1;
}
/* ALWAYS check the return value from scanf() and friends!
* It returns the number of items in your format string successfully
* assigned to. Make sure it matches the number of values you're
* expecting, (one in this case).
*/
if (sscanf(argv[1], "%d", &i) != 1) {
printf("Invalid number\n");
return 1;
}
/* Doesn't get any simpler than an if statement */
if (i < U_LIMIT && i > L_LIMIT)
printf("Within Range\n");
else
printf("Outside Range\n");
return 0;
}
Also, don't try to do crazy optimizations this early in the game. Focus on writing clean, concise code, and let the optimizing compiler take care of the rest for you.
At -O3 optimization level, GCC produces the following assembly for main(). I kept just the interesting part about the integer comparison.
GCC command line: gcc -Wall -Werror -O3 -g test.c
Objdump command line: objdump -d -Mintel -S a.out
if (i < U_LIMIT && i > L_LIMIT)
4004e5: mov eax,DWORD PTR [rsp]
4004e8: add eax,0x63
4004eb: cmp eax,0xc6
4004f0: jbe 400500 <main+0x50>
Note what the compiler did for you. Instead of making two comparisons, it first added 0x63 (99) to i, then, compared that value to 0xC6 (198). This is equivalent to something like:
if ((unsigned int)(i + 99) <= 198)
This way, only one conditional branch was necessary. The cool part is that it does an unsigned comparison. If i was less than -100, then (i + 99) would still be negative, and interpreted as an unsigned integer is 0xfffffed3 (a really big number) which is not <= 198.
And the best part? You didn't even need to think about it!
while (i < strlen(in))
Since your question asks about time optimization then here is a part which you improve on
int n =strlen(in);
while(i<n){
by doing this strlen() is not calculated in each iteration which is time consuming. Rest of the code should be fine as you are using if() to check the bounds which is simpler and best.
Option strtol()
You might want to use just strtol(3):
long int strtol(const char *nptr, char **endptr, int base);
The strtol() function converts the initial part of the string in
nptr to a long integer value according to the given base, which
must be between 2 and 36 inclusive, or be the special value 0.
Furthermore: you will get a return value if the input data overflows or underflows.
Furthermore: the function will place the endptr to the first 'invalid' character.
char* in = "123a";
size_t len = strlen(in);
char* end = NULL;
long int out = strtol(in, &end, 10);
if (out == LONG_MIN || out == LONG_MAX) {
// underflow || overflow
} else if (in + len < end) {
// invalid chars while parsing
} else {
// ok
}
Option sscanf()
The standard alternative is to use sscanf() which is ok in general but might be a bottleneck when you need to parse A LOT of integers (reparsing the format-string is an issue).
Option rollyourown()
Since you roll your own check already you might as well do the parsing yourself (taken from scan_ulong.c of qmail):
unsigned int scan_ulong(const char *s, unsigned long *u) {
unsigned int pos = 0;
unsigned long result = 0;
unsigned long c;
while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) {
result = result * 10 + c;
++pos;
}
if (u) {
*u = result;
}
return pos;
}
This piece is the equivalent of your isdigit() code but also parses the number at the same time. If parsing numbers is a speed issue for your project, consider option strtol() (depends a bit on which compiler / platform you use) or the scan_ulong() variant, otherwise just stick with sscanf().

Confusion about error of program in C

When I compile this code I get an error "in front of int val, there isn't" ;
how can I get rid of this error?
#include <stdio.h>
#include <stdlib.h>
int main()
{
char card_name[3];
puts("카드 이름을 입력하세요: ");
int val = 0;
if(card_name[0]=='K') {
val = 10;
}
else if (card_name[0] == 'Q') {
val = 10;
}
else if (card_name[0] == 'J') {
val = 10;
}
else if (card_name[0] == 'A') {
val = 11;
}
else
{
val = atoi(card_name);
}
printf("카드값은 다음과 같습니다 : %i/n", val);
return 0;
}
Declare all variables in the top of main just after { ,i.e, declare val before the first puts. It is because your compiler uses C89 which forbids mixed declarations and code. From C99 onwards , they can be declared (almost) anywhere.
As mentioned in other answers, C89 does not support declaring variables other than at the start of the block. If you are using clang or gcc, you might want to add '-std=gnu99' to your CFLAGS. If using another compiler or an IDE, look for the language and change it to C99 or higher.
It seems that the compiler requires that all definitions of varaibles would be in the beginninh of block.
Try to write
char card_name[3];
int val = 0;
puts("카드 이름을 입력하세요: ");
Also take into account that array card_name is not initialized.

pointer arithmetic on an array of pointers

Working on a program to split strings into smaller strings with trailing whitespace removed, in an attempt to fully get knowledge of pointers in my head. However, when I try and do pointer arithmetic on a array of pointers, I keep getting a segmentation fault (tested and worked out this was the specific line where the fault occurs); Here's my code:
int enfold(char* to_enfold, long unsigned line_length, char** enfolded) {
int k;
long unsigned char_num = strlen(to_enfold);
if (char_num < line_length) {
for (k = 0; k <= sizeof(to_enfold); k++)
enfolded[0][k] = to_enfold[k];
printf("TOO SHORT\n");
enfolded[0][k] = '\n';
return 1;
}
else {
int i = LINE_LENGTH-1;
while ( to_enfold[i] == ' ' ||
to_enfold[i] == '\t' ||
to_enfold[i] == '\n' ||
i == 0) {
printf("%d\n", i);
i--;
}
for (k = 0; k <= i; k++)
enfolded[0][k] = to_enfold[k];
enfolded[0][k] = '\n';
return 1 + enfold((to_enfold+LINE_LENGTH), line_length, (enfolded+1));
}
}
The problem is with the recursion, which causes a segmentation fault for using arithmetic for (enfolded+1), though not if we overwrite using enfolded. Is there a problem with using pointer arithmetic on pointers to pointers.
One problem is the use of sizeof() in the code:
if (char_num < line_length) {
for (k = 0; k <= sizeof(to_enfold); k++)
enfolded[0][k] = to_enfold[k];
That should be strlen(), except you don't call strlen() in the condition of a loop, and in any case the loop should be written:
strcpy(enfolded[0], to_enfold);
However, that isn't the part of the code where you are seeing the problem. Since you've not shown us how the memory is allocated for enfolded, it is hard to know what you've done, but there's a very good chance that you've not allocated the memory correctly. You should have pre-allocated not only the array of pointers, but also the array that each of the pointers points at (since you don't allocate the space in this code). Alternatively, you need to allocate the requisite space here. You also have not told this function how many pointers are in the array. Fiendishly crafted input can therefore easily cause you to write out of bounds. You need to know how much space there is in the array of pointers.
So, I think you should:
Allocate the strings in this function.
Make sure you free them all when you're done.
Make sure you know how many strings can be stored in the array.
If you're on a system with valgrind then use that to guide you through memory allocation and release.
Please read up on how to create an SSCCE (Short, Self-Contained, Correct Example). One reason why people may not have jumped in to help is that your code self-evidently is not an SSCCE; there is no main() function. Here is an approximation to an SSCCE that works. The main change I made was to ensure that the strings are null terminated; I'm fairly sure that was a large part of your problem.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static
int enfold(char *to_enfold, size_t line_length, char **enfolded)
{
size_t k;
size_t char_num = strlen(to_enfold);
if (char_num < line_length)
{
for (k = 0; k <= char_num; k++)
enfolded[0][k] = to_enfold[k];
printf("TOO SHORT\n");
enfolded[0][k] = '\n';
enfolded[0][k+1] = '\0';
return 1;
}
else
{
size_t i = line_length - 1;
while (to_enfold[i] == ' ' ||
to_enfold[i] == '\t' ||
to_enfold[i] == '\n' ||
i == 0)
{
printf("%zu\n", i);
i--;
}
for (k = 0; k <= i; k++)
enfolded[0][k] = to_enfold[k];
enfolded[0][k] = '\n';
enfolded[0][k+1] = '\0';
return 1 + enfold((to_enfold + line_length), line_length, (enfolded + 1));
}
}
int main(void)
{
enum { SIZE = 100 };
char *enfolded[SIZE];
for (int i = 0; i < SIZE; i++)
enfolded[i] = malloc(sizeof(char) * SIZE);
char line[4096];
while (fgets(line, sizeof(line), stdin) != 0)
{
int n = enfold(line, 8, enfolded);
assert(n < SIZE);
for (int i = 0; i < n; i++)
printf("%d: <<%s>>\n", i, enfolded[i]);
printf("Parts: %d\n", n);
}
for (int i = 0; i < SIZE; i++)
free(enfolded[i]);
return 0;
}
Sample run:
$ ./mem <<< "Hello, how are you today?"
TOO SHORT
0: <<Hello, h
>>
1: <<ow are y
>>
2: <<ou today
>>
3: <<?
>>
Parts: 4
$
Checking with valgrind gives the code a clean bill of health. However, you might need to think about what happens if you have 30 blanks in the middle of the string (my strong suspicion is that you'll run into problems, but I've not proven that).
Compilation with GCC 4.8.2 on Mac OS X 10.9.1 Mavericks:
gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Werror mem.c -o mem
I pretty much don't compile with less stringent compilation options than that (unless it needs to be C99 or, perish the thought, C89 code). Note that the code does use some C99 features, notably declarations of variables in the for loop.

Undefined reference to function - Learning C

I'm learning C by translating some of the things I have done in Python to C. I have tried to look online as much as I can before coming here but it seems really difficult to find answers to what I'm looking for.
What follows is my (so-far) translation of the Miller-Rabin test for a number's primality.
#include <stdio.h>
#include <math.h>
_Bool prime(long long n);
int main() {
int i = 6;
for (i; i < 9; i++) {
if (prime(i)) {
printf("%i\n", prime(i));
}
}
}
_Bool prime(long long n) {
int s = 0;
int r = 0;
int a_index = 0;
// printf("the value of a_index when initialised is: %d\n", a_index);
// printf("the value of s when initialised is: %d\n", s);
int *a_list;
_Bool is_prime = 1;
_Bool composite_part_a = 1;
_Bool composite_part_b = 1;
long long d = n - 1;
while (d % 2 == 0) {
s++;
d = d / 2;
}
if (4759123141 <= n && n < 2152302898747) {
// malloc
a_list[0] = 2;
a_list[1] = 3;
a_list[2] = 5;
a_list[3] = 7;
a_list[4] = 11;
}
else if (9080191 <= n && n < 4759123141) {
// malloc
a_list[0] = 2;
a_list[1] = 7;
a_list[2] = 61;
}
else if (1373653 <= n && n < 9080191) {
// malloc
a_list[0] = 31;
a_list[1] = 73;
}
else if (4 <= n && n < 1373653) {
a_list = (int *) malloc(sizeof(int) * 2);
a_list[0] = 2;
a_list[1] = 3;
printf("the value of a_list[0] upon its first assignment is: %d\n", a_list[0]);
// printf("the first element of a_list is: %d\n", a_list[0]);
// printf("the second element of a_list is: %d\n", a_list[1]);
}
else if (n == 3 | n == 2) {
return 1;
}
else if (n % 2 == 0 | n == 1) {
return 0;
}
printf("the value of a_list[0] over here is: %d\n", a_list[0]);
// printf("%d\n", a_list[1]);
for (a_index; a_index < sizeof(a_list) / sizeof(int); a_index++) {
printf("test");
if ((long long)pow(a_index[a_list], d) % n != 1) {
composite_part_a = 1;
}
else {
composite_part_a = 0;
}
// printf("the value of r is: %d\n", r);
// printf("the value of s is: %d\n", s);
for (r; r < s; r++) {
printf("%lld\n", (int)pow(a_list[a_index], exp2(r) * d) % n);
if ((long long)pow(a_index[a_list], exp2(r) * d) % n != -1) {
composite_part_b = 1;
}
else {
composite_part_b = 0;
break;
}
}
if (composite_part_a && composite_part_b) {
return 0;
}
}
return is_prime;
}
The trouble with learning C is there isn't much good literature for pure beginners, outside of what I hear about K&R but that's in the mail and I can't get my hands on it right now. The program returns these errors:
3.c: In function ‘prime’:
3.c:52:26: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
/tmp/ccGQnk9T.o: In function `prime':
3.c:(.text+0x272): undefined reference to `pow'
3.c:(.text+0x2b9): undefined reference to `exp2'
3.c:(.text+0x2db): undefined reference to `pow'
3.c:(.text+0x30b): undefined reference to `exp2'
3.c:(.text+0x32d): undefined reference to `pow'
collect2: ld returned 1 exit status
First off, haven't I included to introduce pow and else? I know it's not proper to ask two questions and my main question is about pow and exp2, but if you do have a suggestion about the malloc as well feel free to include it.
You need to link with the math library as well, it's not included by default.
Something like the following command:
$ gcc 3.c -lm
Notice the -lm argument... It tells the linker to add a library (the -l part) and the name of the library (the m part).
Math functions are part of libm. Link them when you compile with -lm.
3.c:52:26: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
Is caused by a missing include, malloc() is defined in stdlib.h so need to include that.
3.c:(.text+0x272): undefined reference to `pow' (and the rest)
Is caused by a missing link to libm. Most (if not all) methods in math.h are not in standard libc that always gets linked but in libm instead.
How to link differs between compiler, but for gcc (and many other unix compilers):
gcc 3.c -o 3 -lm
Where "-lm" tells gcc to link libm.
You need to include <stdlib.h> for malloc and free.
For the math stuff to work you have to link it,
gcc 3.c -lm
Where -l is the library flag and m is tell it to use the math library
Also you need to move the definition of prime to above main, things need to be declared in order.
Since you are just starting here are some other helpful flags for the compiler
-g this will give better debugging when using valgrind or gdb.
-o lets you define the compiled file name eg: gcc 3.c -o 3 will create ./3 instead of ./a.out

Unreasonable error calling function in C - Program to sort an array

I wrote a program that receive from user a series of numbers (<=20) while the last '0' means end of series (not included in series storing).
2 arrays (x,y) size 20 (0-19 + 1 for the '0') must be zeros, and m means number of organs in Y array.
The user must enter numbers ascending (it is ok 4ex. 1,2,2,3,7,8,...,0) and end with a '0' of course, if not, appropriate error message will appear, and program will shut off.
We can be sure the user will keep the <=20 numbers of input.
Y array will be (if everything went ok with X array) a sorted array of X but without duplicates.
'm' will be number of organs in Y exclude '0' of course.
Function SIFT must only organize the Y array for being printed from main().
Example:
If user will store in X: 1,1,2,3,5,5,5,6
On screen will be: m = 5 Y = 1,2,3,5,6
My tryout:
#include <stdio.h>
#include <string.h>
void SIFT(int x_arr[ ], int y_arr[]);
int main ()
{
int x[20] = {0} , y[20] = {0};
int m=0,temp=0,curr=0,i=0,j=0;
printf("Please enter your numbers now:\n\n");
/*enter numbers one by one. if x[i+1] value < x[i] value, err msg.
when user want to end the series he must enter '0' which means end of string (it wont included in x[]) */
while ( ( temp = getchar() ) != '0' )
{
if (temp >= curr)
{
x[i] = temp;
curr = temp;
i++;
}
else
{
printf("The numbers are not at the right order !\n\nProgram will now terminate...\n\n");
}
}
SIFT(x,y);
for (i=0 ; y[i]=='0' ; i++) /*strlen(y) without ('0')'s includes*/
m++;
/*Prints m , y's organs*/
printf("\n\nm = %d",m);
printf("Y = ");
while (y[j]!='0')
{
printf ("%d ,",y[j]);
j++;
}
void SIFT(int x_arr[ ], int y_arr[])
{
int i=0,j=0;
while (x_arr[i] != '0')
{
if (x_arr[i] == x_arr[i+1]) /*if current val. equals next val. -> jump dbl at x_arr*/
{
y_arr[j] = x_arr[i];
i+=2;
j++;
}
else
{
y_arr[j]=x_arr[i];
i++;
j++;
}
}
}
return 0;
}
The error I'm getting from the gcc is:
gcc -g -ansi -pedantic -Wall 2.c -o 2
2.c: In function ‘main’:
2.c:43: warning: ISO C forbids nested functions
2.c:43: warning: ISO C90 forbids mixed declarations and code
/tmp/ccyZNfkF.o: In function `main':
/home/student/Desktop/2/2.c:29: undefined reference to `SIFT'
collect2: ld returned 1 exit status
make: *** [2] Error 1
And another question:
I would like to convert this code to the MIPS Assembly code, is there a short and fast way to do so ?
Thanks all you guys !!
You didn't close main function before declaration of SIFT, so SIFT is declared inside of main which is forbidden.
Fix it by returning from main before the definition of SIFT():
...
return 0;
}
void SIFT(int x_arr[ ], int y_arr[])
{
int i=0,j=0;
...

Resources