I created a program in C and I tried to compile it. When I use my gcc 4.8.1 compiler in Widows everything worked and my program too.
I compiled with the following arguments:
gcc -std=c99 -O2 -DCONTEST -s -static -lm children.c
But in linux I getting the following error:
/usr/lib/gcc/i486-linux-gnu/4.7/../../../i386-linux-gnu/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: error: ld returned 1 exit status
Why is that? My programm is working and I can't understand why I getting compiling errors in linux.
My code is:
/*---------------------*/
/* included files */
/*---------------------*/
#include <stdio.h>
#include <stdlib.h>
/*---------------------*/
/* defined constants */
/* for restriction */
/*---------------------*/
#define MIN 1
#define MAX 1000000
#define IOERROR 5 // 'Input/Output Error'
/*---------------------*/
/* function prototypes */
/*---------------------*/
int main();
FILE *read_input(const char *filename_r);
int count_children(FILE *input);
int pass_heights(FILE *input, int *children, int size);
int check_tall(const int *children, int size);
void write_output(const int total,const char *filename_w);
/*---------------------*/
/* start of program */
/*---------------------*/
int main() {
const char *filename_r = "xxx.in";
const char *filename_w = "xxx.out";
FILE *input = read_input(filename_r);
int size = count_children(input);
int *children = malloc(size * sizeof *children);
if (children==NULL)
exit(1); //General application error
pass_heights(input, children, size);
fclose(input);
int total = check_tall(children, size);
free(children);
write_output(total,filename_w);
return 0;
}
FILE *read_input(const char *filename_r) {
FILE *input = fopen(filename_r, "r");
if(input == NULL)
exit(IOERROR);
return input;
}
int count_children(FILE *input) {
int count = 0;
fscanf(input, "%d",&count);
if(count > MAX || count < MIN)
exit(1); //General application error
return count;
}
int pass_heights(FILE *input, int *children, int size) {
for(int i = 0; i < size; i++)
fscanf(input, "%d",&children[i]);
return *children;
}
int check_tall(const int *children, int size) {
int total = 0;
int tmp_max = 0;
for(int i = size - 1; i >= 0; i--)
{
if(children[i] > tmp_max) {
tmp_max = children[i];
total++;
}
}
return total;
}
void write_output(const int total,const char *filename_w) {
FILE *output = fopen(filename_w, "w");
if(output == NULL)
exit(IOERROR);
fprintf(output, "%d\n", total);
fclose(output);
}
You used -static option, which modifies the way executable is linked.
I was unable to reproduce your exact error message, but on my Linux it says that it is unable to link with -lc in static mode, and under my OSX it says that it is unable to locate -lcrt0.o. For me in both case, this means that the system is unable to locate the static stub.
If you remove -static it should work. If not, your problem is very strange.
The error you show indicates the linker is not finding the main() function in your code. As it is evident that you have included it in the source file, it is also evident you are not compiling with that command line (or you are compiling in other directory where you have a non-main() source called children.c, perhaps the build system makes a touch children.c if it doesn't find the source, and then compiles it --on that case it will not have a main() routine). Check that the files are properly created and where, as I think you aren't compiling that file anyway.
Try to use simple options before you go to more complicated ones. Try something like:
gcc -std=c99 -o children children.c
before trying to experiment with optimization or static linking anyway. Also, dynamic linking is normally better than static, so you'll get smaller executables (8Kb vs. 800Kb, and multiple copies of libc loaded per executable). Also, you don't need to include -lm as you aren't using any of the <math.h> functions (having it doesn't hurt anyway).
I have compiled your source with the following command line without any problem, but I do have support for statically linked executables and perhaps you don't (the command line I have put above would work in any linux, I suppose)
$ make CC='gcc' CFLAGS='-std=c99 -O2 -DCONTEST' LDFLAGS='-s -static -lm' children
gcc -std=c99 -O2 -DCONTEST -s -static -lm children.c -o children
children.c: In function ‘pass_heights’:
children.c:81:11: warning: ignoring return value of ‘fscanf’, declared with attribute warn_unused_result [-Wunused-result]
children.c: In function ‘count_children’:
children.c:69:11: warning: ignoring return value of ‘fscanf’, declared with attribute warn_unused_result [-Wunused-result]
Related
I am trying to compile this program https://gist.github.com/jrabbit/1042021
I am using this https://doc.opensuse.org/projects/satsolver/11.2/sha1_8h_source.html sha1.h file. However if I try to compile the program gcc gives me the following error (gcc on windows)
c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../libmingw32.a(main.o):(.text.start
up+0xa0): undefined reference to `WinMain#16'
collect2.exe: error: ld returned 1 exit status
gcc did not recognise type u_int32_t so I changed them to unit32_t in sha1.c code
What could be wrong there?
The library doesn't have main function. Any C program must have a main function to compile.
So either you create a main.c file and include the library in it.
Or in line 251 of sha1.c change #if 0 to #if 1 which will open the template main function included in the library.
Note that the template 'main` function has some bugs. Replace it with something like that:
#define BUFSIZE 10
int
main(int argc, char **argv)
{
SHA1_CTX ctx;
unsigned char hash[20], buf[BUFSIZE];
int i;
for(i=0;i<BUFSIZE;i++)
{
buf[i] = i + '0';
printf("%i", i);
}
printf("\n");
SHA1Init(&ctx);
for(i=0;i<BUFSIZE;i++)
SHA1Update(&ctx, buf + i, 1);
SHA1Final(hash, &ctx);
printf("SHA1=");
for(i=0;i<20;i++)
printf("%02x", hash[i]);
printf("\n");
return 0;
}
This is my main file
#include<stdio.h>
#include<string.h>
#include "ssv.c"
int main() {
int i,length,acct;
float amnt;
char data[1000], record[1000];
FILE *x = fopen("students.ssv","rt");
while(!feof(x)) {
for (i = 0; data[i] != '\n'; i++) {
record[i] = data[i];
length = i + 1;
}
record[length] = '\0';
parse(record,&acct,&amnt);
fgets(data,999,x);
}
fclose(x);
return 0;
}
This is my ssv.c file
#include<stdio.h>
void parse(char record[], int *acct, float *amnt){
sscanf(record,"%d %f",acct,amnt);
}
For some reason, these two programs are not working very well together. I am still getting used to modular programming. I keep getting the messages "undefined reference to main" and "multiple definition of".
My main goal here is to parse a file like
100 -10.5
13 -2.4
into corresponding fields. Please advise!
The first iteration of the while loop uses data before it has read the line. It should be:
while(fgets(data, sizeof data, x)) {
parse(data,&acct,&amnt);
}
You don't need to subtract 1 from the size of data when calling fgets().
There's no reason to copy data to record. You can simply parse data (the parse() function will ignore the newline). fgets() ends the string with a null terminator, you don't need to add it yourself.
#include should only be used for .h files, not .c files. You combine object files using the linker. So get rid of #include "ssv.c", replace it with #include "ssv.h". This file should just contain a declaration of parse().
void parse(char record[], int *acct, float *amnt);
Compile the two programs using:
gcc main.c ssv.c
Or you can compile each file separately then link them:
gcc -c main.c
gcc -c ssv.c
gcc main.o ssv.o
I just read about init and fini sections in ELF files and gave it a try:
#include <stdio.h>
int main(){
puts("main");
return 0;
}
void init(){
puts("init");
}
void fini(){
puts("fini");
}
If I do gcc -Wl,-init,init -Wl,-fini,fini foo.c and run the result the "init" part is not printed:
$ ./a.out
main
fini
Did the init part not run, or was it not able to print somehow?
Is there a any "official" documentation about the init/fini stuff?
man ld says:
-init=name
When creating an ELF executable or shared object, call
NAME when the executable or shared object is loaded, by
setting DT_INIT to the address of the function. By
default, the linker uses "_init" as the function to call.
Shouldn't that mean, that it would be enough to name the init function _init? (If I do gcc complains about multiple definition.)
Don't do that; let your compiler and linker fill in the sections as they see fit.
Instead, mark your functions with the appropriate function attributes, so that the compiler and linker will put them in the correct sections.
For example,
static void before_main(void) __attribute__((constructor));
static void after_main(void) __attribute__((destructor));
static void before_main(void)
{
/* This is run before main() */
}
static void after_main(void)
{
/* This is run after main() returns (or exit() is called) */
}
You can also assign a priority (say, __attribute__((constructor (300)))), an integer between 101 and 65535, inclusive, with functions having a smaller priority number run first.
Note that for illustration, I marked the functions static. That is, the functions won't be visible outside the file scope. The functions do not need to be exported symbols to be automatically called.
For testing, I suggest saving the following in a separate file, say tructor.c:
#include <unistd.h>
#include <string.h>
#include <errno.h>
static int outfd = -1;
static void wrout(const char *const string)
{
if (string && *string && outfd != -1) {
const char *p = string;
const char *const q = string + strlen(string);
while (p < q) {
ssize_t n = write(outfd, p, (size_t)(q - p));
if (n > (ssize_t)0)
p += n;
else
if (n != (ssize_t)-1 || errno != EINTR)
break;
}
}
}
void before_main(void) __attribute__((constructor (101)));
void before_main(void)
{
int saved_errno = errno;
/* This is run before main() */
outfd = dup(STDERR_FILENO);
wrout("Before main()\n");
errno = saved_errno;
}
static void after_main(void) __attribute__((destructor (65535)));
static void after_main(void)
{
int saved_errno = errno;
/* This is run after main() returns (or exit() is called) */
wrout("After main()\n");
errno = saved_errno;
}
so you can compile and link it as part of any program or library. To compile it as a shared library, use e.g.
gcc -Wall -Wextra -fPIC -shared tructor.c -Wl,-soname,libtructor.so -o libtructor.so
and you can interpose it into any dynamically linked command or binary using
LD_PRELOAD=./libtructor.so some-command-or-binary
The functions keep errno unchanged, although it should not matter in practice, and use the low-level write() syscall to output the messages to standard error. The initial standard error is duplicated to a new descriptor, because in many instances, the standard error itself gets closed before the last global destructor -- our destructor here -- gets run.
(Some paranoid binaries, typically security sensitive ones, close all descriptors they don't know about, so you might not see the After main() message in all cases.)
It is not a bug in ld but in the glibc startup code for the main executable. For shared objects the function set by the -init option is called.
This is the commit to ld adding the options -init and -fini.
The _init function of the program isn't called from file glibc-2.21/elf/dl-init.c:58 by the DT_INIT entry by the dynamic linker, but called from __libc_csu_init in file glibc-2.21/csu/elf-init.c:83 by the main executable.
That is, the function pointer in DT_INIT of the program is ignored by the startup.
If you compile with -static, fini isn't called, too.
DT_INIT and DT_FINI should definitely not be used, because they are old-style, see line 255.
The following works:
#include <stdio.h>
static void preinit(int argc, char **argv, char **envp) {
puts(__FUNCTION__);
}
static void init(int argc, char **argv, char **envp) {
puts(__FUNCTION__);
}
static void fini(void) {
puts(__FUNCTION__);
}
__attribute__((section(".preinit_array"), used)) static typeof(preinit) *preinit_p = preinit;
__attribute__((section(".init_array"), used)) static typeof(init) *init_p = init;
__attribute__((section(".fini_array"), used)) static typeof(fini) *fini_p = fini;
int main(void) {
puts(__FUNCTION__);
return 0;
}
$ gcc -Wall a.c
$ ./a.out
preinit
init
main
fini
$
I am trying to use two .c files together. I am lost at how to do this, I have a simple setup for each file but I get a undefined reference to format_lines error when I try to compile. Any help would be muchly appreciated;
formatter.h
#ifndef _FORMATTER_H_
#define _FORMATTER_H_
#include <stdio.h>
char **format_file(FILE *);
char **format_lines(char **, int);
void test();
#endif
formatter.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "formatter.h"
char **format_file(FILE *infile) {
return NULL;
}
char **format_lines(char **lines, int num_lines) {
char **result = NULL;
#ifdef DEBUG
result = (char **)malloc(sizeof(char *) * 2);
if (result == NULL) {
return NULL;
}
result[0] = (char *)malloc(sizeof(char) * 80);
if (result[0] == NULL) {
return NULL;
}
strncpy(result[0], "(machine-like voice) EXTERMINATE THEM!", 79);
result[1] = (char *)malloc(sizeof(char) * 2);
if (result[1] == NULL) {
return NULL;
}
result[1][0] = '\0';
#endif
}
void test(){
print("here");
}
and sengfmt.c
#include <stdio.h>
#include <stdlib.h>
#include "formatter.h"
int main(int argc, char *argv[]) {
test();
#ifdef DEBUG
printf("%s does nothing right now.\n", argv[0]);
#endif
exit(0);
}
When I try to compile, I just type this.
$ gcc sengfmt3.c
/tmp/cc7Ttgne.o: In function `main':
sengfmt3.c:(.text+0x15): undefined reference to `test'
collect2: ld returned 1 exit status
I suspect that your main used to try to call format_lines
You need to do this
gcc formatter.c sendgfmt.c -o myprog
You must list all the c files that you want compiled together
If you have code in multiple source files, then you need to build with all the source files.
There are two ways of doing this:
Compile and link all source files using using one command:
$ gcc sengfmt3.c someOtherSourceFile.c someThirdSourceFile.c
First make object files of all source files, and then link the object files together. This is more work, but if you have a makefile or other build-system it will be better since only the modified source files will be recompiled, and might save you some build-time:
$ gcc -c sengfmt3.c
$ gcc -c someOtherSourceFile.c
$ gcc -c someThirdSourceFile.c
$ gcc sengfmt.o someOtherSourceFile.o someThirdSorceFile.o
Note the command-line option -c for the compilation, this tells GCC to generate object files. Also note that for the linking command (the last one) the file extensions have changed from .c to .o.
The command in point 1 does this internally, using temporary files which are removed when done.
Here is some code from Ben Straub's (link blog) that I am basing this on:
static int do_clone(const char *url, const char *path)
{
git_repository *repo = NULL;
int ret = git_clone(&repo, url, path, NULL);
git_repository_free(repo);
return ret;
}
And here is my code:
#include <git2.h>
int main(void) {
git_repository *out = NULL;
git_clone(&out, "https://github.com/lehitoskin/racketball", "/home/maxwell", NULL);
return 0;
}
I am very inexperienced with C, so I apologize for having such elementary problems. Anyway, here is the error my compiler gives me:
maxwell#max-pc ~ $ gcc -I libgit2/include gitfun.c
/tmp/ccB64nPh.o: In function `main':
gitfun.c:(.text+0x31): undefined reference to `git_clone'
collect2: error: ld returned 1 exit status
Why can't I call git_clone this way?
It looks like you didn't link to the library. Add -lgit2 if libgit2 is the lib name.
gcc -I libgit2/include gitfun.c -L<path to lib> -l<libname minus the "lib" part>
IOW, you compile fine but when the linker goes looking for git_clone it can't find it because you haven't specified the library that it is in.