Suddenly started getting this error at link time on some older code. I managed to replicate the problem with a very simple snippet of code:
#include <poll.h>
#include <stdio.h>
typedef struct
{
struct pollfd m_fds[6000];
nfds_t m_count;
} PollWrapper;
static PollWrapper g_pollWrapper;
int main()
{
return poll(g_pollWrapper.m_fds, g_pollWrapper.m_count, 0);
}
Compiling without -flto is fine.
gcc -Wall -O3 -o poll.exe poll.c # gcc 4.8.1-10ubuntu9
# successful
But adding -flto causes an error when linking:
gcc -Wall -O3 -flto -o poll.exe poll.c # gcc 4.8.1-10ubuntu9
# error
gcc -Wall -O3 -flto -o poll.o -o poll.c
# compilation is fine
gcc -Wall -O3 -flto -o poll.exe poll.o
# linking fails
/usr/include/x86_64-linux-gnu/bits/poll2.h: In function `main`:
/usr/include/x86_64-linux-gnu/bits/poll2.h:41:2: warning: call to `__poll_chk_warn` > declared with attribute warning: poll called with fds buffer too small file nfds entries [enabled by default]
return __poll_chk (__fds, __nfds, __timeout, __bos (__fds));
^
Having read related questions, I tried explicitly enabling and disabling the linker plugin, neither had any effect.
This only appears to happen with an array, none of the following have the same problem:
struct pollfd f;
int numfds = poll(&f, g_pollWrapper.m_size, duration);
or
struct pollfd fds[6000];
int numfds = poll(&f, g_pollWrapper.m_size, duration);
etc.
Am I either missing something obvious or is this an LTO defect in my GCC, and if so is there a way I can work around it?
Related
I recently came across the following warning in one of my applications that uses the GLib:
warning: ISO C prohibits argument conversion to union type [-Wpedantic]
note: in definition of macro '_G_DEFINE_BOXED_TYPE_BEGIN'
2147 | _g_register_boxed (g_intern_static_string (#TypeName), copy_func, free_func);
I usually compile with -wpedantic and it was the first time for me to get a warning that couldn't be traced down to my code, but seems to be caused by the internals of the _G_DEFINE_BOXED_TYPE_BEGIN-macro. The warning seems to appear whenever G_DEFINE_BOXED_TYPE is used with a dedicated free or copy function.
An example application may look as the following:
/* boxed_warning.c
* Produces warning, when compiled with:
* $ cc `pkg-config --cflags glib-2.0` -Wextra -Wpedantic -Wall -std=gnu11 -O0 -g -o 'boxed_warning.c.o' -c boxed_warning.c
*/
#include <glib.h>
#include <gio/gio.h>
struct _FooBoxed { gdouble x; };
typedef struct _FooBoxed FooBoxed;
static FooBoxed *
foo_boxed_copy (const FooBoxed *boxed)
{
FooBoxed *result = g_new (FooBoxed, 1);
*result = *boxed;
return result;
}
G_DEFINE_BOXED_TYPE (FooBoxed, foo_boxed, (GBoxedCopyFunc) foo_boxed_copy, (GBoxedFreeFunc) g_free)
I'm using glib 2.62.4, but I can reproduce the warning even when compiling with the latest version from git.gnome.org.
Has anyone else experienced this warning when working with the GLib2.0 and found a work-around? Or is the warning indeed related to a wrong usage of the mentioned macro by my code?
I had to create a file.h which I put into my includes/ directory.
I meet a problem when comes time to GCC:
The error I get is:
error: invalid value 'precompiled-header' in '-x precompiled-header'
And I have absolutely no idea about what causes this!
Here is my main, ask me if you need to see more of my code.
I compile with this line of command : gcc -Wall -Wextra -Werror main.c includes/* srcs/* do-op.c
#include "includes/ft.h"
int main(int ac, char **av)
{
int a;
int b;
char c;
(void)ac;
a = ft_atoi(av[1]);
b = ft_atoi(av[3]);
c = av[2][0];
ft_putnbr(ft_do_op(a, b, c));
}
You state that your command to build is:
gcc -Wall -Wextra -Werror main.c includes/* srcs/* do-op.c
That means you're compiling the header files, which you normally should not do. What you should do is tell the compiler where it can find the header files, which is done with the -I (upper case i) option:
gcc -Wall -Wextra -Werror -Iincludes main.c srcs/* do-op.c
I compile this code main.c in CentOS7 with gcc:
#include <pthread.h>
void* mystart(void* arg)
{
pthread_yield();
return(0);
}
int main(void)
{
pthread_t pid;
pthread_create(&pid, 0, mystart, 0);
return(0);
}
1st compile: gcc -Wall -g main.c -pthread -o a.out
It's all OK.
2nd compile: gcc -Wall -g main.c -lpthread -o a.out
Gives
warning: implicit declaration of function 'pthread_yield' [-Wimplicit-function-declaration]
Can the 2nd a.out still run correctly ?
How to fix the warning without -pthread? Is sched_yield another way to yield a pthread ?
pthread_yield() is a non-standard function which is typically enabled by defining
#define _GNU_SOURCE
While you should use -pthread for compiling, I would expect you to get the same warning with both compilations (unless -pthread defines _GNU_SOURCE which may be the case).
The correct way to fix is to not use the non-standard function pthread_yield() and use the POSIX function sched_yield() instead by including #include <sched.h>.
You should use -pthread for compile and link. It not only links the library, it also sets preprocessor defines and sometimes selects a different runtime library (on Windows for example).
I have the next code :
test.c
#include "a1.h"
int main() {
int a = 8;
foo(a);
return a;
}
a1.h
void foo (int a);
a1.c
int f = 0;
void foo (int a, int b){
f=5+a+b;
return;
}
Pay attention that in a1.c foo has 1 more parameter than the prototype defined in a1.h.
The compiler isn't issue a warning or an error and so as coverity :
make all
Building file: ../src/a1.c
Invoking: GCC C Compiler
gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/a1.d" -MT"src/a1.d" -o "src/a1.o" "../src/a1.c"
Finished building: ../src/a1.c
Building file: ../src/test.c
Invoking: GCC C++ Compiler
gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/test.d" -MT"src/test.d" -o "src/test.o" "../src/test.c"
Finished building: ../src/test.c
Building target: test
Invoking: GCC C++ Linker
gcc -o "test" ./src/a1.o ./src/test.o
Finished building target: test
How can I defend myself in those cases ? I know that if I will add #include "a1.h" in the a1.c file I will get an error but is there a way to get an error without the "include " ?
Compiler isn't issuing a warning because it does not know that foo(int) from a1.h header and foo(int,int) from a1.c file is the same function. C++ allows functions to be overloaded, so both functions could potentially coexist. That is why C++ compiler cannot detect this problem, so you need to wait until the linking stage.
If you were compiling using C, not C++, you could have the compiler detect this condition simply by including a1.h at the top of a1.c file.
You're overloading foo. The version with only one parameter is never defined, hence you should get a linker error when using it.
How can I defend myself in those cases ?
You can't defend yourself from function overloading. Just make sure that you've got the same signature in both the header as the source file.
I'm trying to compile a C program that uses libvncserver but no matter what I do I keep getting undefined reference errors, the library I'm having troubles with is rfb/rfb.h.
vnc.c code (copied from here):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rfb/rfb.h>
#define WIDTH 640
#define HEIGHT 480
#define BPP 4
/* 15 frames per second (if we can) */
#define PICTURE_TIMEOUT (1.0/15.0)
/*
* throttle camera updates
*/
int TimeToTakePicture() {
static struct timeval now={0,0}, then={0,0};
double elapsed, dnow, dthen;
gettimeofday(&now,NULL);
dnow = now.tv_sec + (now.tv_usec /1000000.0);
dthen = then.tv_sec + (then.tv_usec/1000000.0);
elapsed = dnow - dthen;
if (elapsed > PICTURE_TIMEOUT)
memcpy((char *)&then, (char *)&now, sizeof(struct timeval));
return elapsed > PICTURE_TIMEOUT;
}
/*
* simulate grabbing a picture from some device
*/
int TakePicture(unsigned char *buffer)
{
static int last_line=0, fps=0, fcount=0;
int line=0;
int i,j;
struct timeval now;
/*
* simulate grabbing data from a device by updating the entire framebuffer
*/
for(j=0;j<HEIGHT;++j) {
for(i=0;i<WIDTH;++i) {
buffer[(j*WIDTH+i)*BPP+0]=(i+j)*128/(WIDTH+HEIGHT); /* red */
buffer[(j*WIDTH+i)*BPP+1]=i*128/WIDTH; /* green */
buffer[(j*WIDTH+i)*BPP+2]=j*256/HEIGHT; /* blue */
}
buffer[j*WIDTH*BPP+0]=0xff;
buffer[j*WIDTH*BPP+1]=0xff;
buffer[j*WIDTH*BPP+2]=0xff;
}
/*
* simulate the passage of time
*
* draw a simple black line that moves down the screen. The faster the
* client, the more updates it will get, the smoother it will look!
*/
gettimeofday(&now,NULL);
line = now.tv_usec / (1000000/HEIGHT);
if (line>HEIGHT) line=HEIGHT-1;
memset(&buffer[(WIDTH * BPP) * line], 0, (WIDTH * BPP));
/* frames per second (informational only) */
fcount++;
if (last_line > line) {
fps = fcount;
fcount = 0;
}
last_line = line;
fprintf(stderr,"%03d/%03d Picture (%03d fps)\r", line, HEIGHT, fps);
/* success! We have a new picture! */
return (1==1);
}
/*
* Single-threaded application that interleaves client servicing with taking
* pictures from the camera. This way, we do not update the framebuffer
* while an encoding is working on it too (banding, and image artifacts).
*/
int main(int argc,char** argv)
{
long usec;
rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,WIDTH,HEIGHT,8,3,BPP);
if(!server)
return 0;
server->desktopName = "Live Video Feed Example";
server->frameBuffer=(char*)malloc(WIDTH*HEIGHT*BPP);
server->alwaysShared=(1==1);
/* Initialize the server */
rfbInitServer(server);
/* Loop, processing clients and taking pictures */
while (rfbIsActive(server)) {
if (TimeToTakePicture())
if (TakePicture((unsigned char *)server->frameBuffer))
rfbMarkRectAsModified(server,0,0,WIDTH,HEIGHT);
usec = server->deferUpdateTime*1000;
rfbProcessEvents(server,usec);
}
return(0);
}
Compiler output:
sudo gcc -g -Wall -Wextra -O2 vnc.c
/tmp/cc7dpMCs.o: In function `main':
/home/arcm/Projects/c/vnc.c:77: undefined reference to `rfbGetScreen'
/home/arcm/Projects/c/vnc.c:84: undefined reference to `rfbInitServerWithPthreadsAndZRLE'
/home/arcm/Projects/c/vnc.c:91: undefined reference to `rfbProcessEvents'
/home/arcm/Projects/c/vnc.c:86: undefined reference to `rfbIsActive'
/home/arcm/Projects/c/vnc.c:89: undefined reference to `rfbMarkRectAsModified'
collect2: error: ld returned 1 exit status
I've got libvncserver0 and libvncserver-dev installed and i'm using ubuntu 14.04.
I tried:
sudo gcc -g -Wall -Wextra -O2 vnc.c -lm
sudo gcc -g -Wall -Wextra -O2 vnc.c -ldl
sudo gcc -g -Wall -Wextra -O2 -ldl vnc.c
sudo gcc -g -Wall -Wextra -O2 -I/usr/include/rfb -L/usr/include/rbf/rfb.h vnc.c
sudo gcc -g -Wall -Wextra -O2 -I/usr/include/rfb vnc.c
sudo gcc -g -Wall -Wextra -O2 -L/usr/include/rbf/rfb.h vnc.c
sudo gcc -g -Wall -Wextra -O2 /usr/include/rbf/rfb.h vnc.c
sudo gcc -g -Wall -Wextra -O2 -L/usr/include/rbf/rfb.h -ldl vnc.c
But I get the same errors everytime. What am I doing wrong and how can I fix it?
You don't "link" a library header, you include it so the compiler sees the library's declarations at compile time and knows that rfbGetScreen() is a function that takes so-and-so many arguments of this-and-that type and returns a rfbScreenInfoPtr. How it does this (the definition of the function) is not important to the compiler. It just adds a reference to that function, which is left for the linker to resolve. (Note the vocabulary here.)
You link your compiled code to the library binary. This is done by the linker, in a different (and later) step that just happens to be supported by the same frontend as compiling your source (gcc). In this step, any of the library functions that your code actually uses (references) are resolved by linking them in from the specified libraries.
This here...
sudo gcc -g -Wall -Wextra -O2 vnc.c
...links only the standard library and runtime, as there are no specific linking instructions in there.
This here...
-L/usr/include/rbf/rfb.h
...is nonsense, as -L is for giving directories where library binaries should be looked for (and is not necessary if the library in question is installed in the standard location).
The actual link instruction is -l. If you state -lfoo, then the library libfoo is searched for any undefined references.
This here...
-ldl
...is linking libdl, and from that you should be able to deduce that...
-lvncserver
...is what you're looking for (assuming that <rfb/rfb.h> actually does refer to libvncserver, which I don't know).
Note that the linker is processing libraries in the sequence they are given on the command line, so you need to state -lvncserver after vnc.c, because only then does the linker know which undefined references it ought to be looking for in libvncserver.
And never, ever run a compiler as sudo. Why in {.....}'s name do you think this would be necessary?