GCC compiling error, uncertain what to change - c

I am trying to compile an old C program on Centos8 Linux and it is failing, i'd appreciate any help.
I have broken below into the Makefile used, the error and code.
Any help would be much appreciated.
Thank you.
Makefile:
CC = gcc
C_FLAGS = -Wall -O0 -ggdb -march=i686 -m32 -DDEBUG=1
C_FLAGS2 = -Wall -O4 -march=i686 -s
LIBS = -lcrypt -lmysqlclient
Error
gcc -c -Wall -O0 -ggdb -march=i686 -m32 -DDEBUG=1 chat.c
In file included from chat.c:12:
command.h:152:30: error: array type has incomplete element type ‘struct cmd_type’
extern const struct cmd_type cmd_table[];
^~~~~~~~~
command.h
#ifndef _COMMAND_H
#define _COMMAND_H
/* returns 0 if not a command, or if the command is handled "on the fly".
otherwise, it handles it and returns 1 */
int execute_command(request_rec *r);
/* does that "print everything you've got" thing */
void archive_command(request_rec *r, user_rec **user_list,
message_rec **message_list, char *title, char *topic,
int chat_open);
#define DECLARE_CHAT_CMD( cmd ) CHAT_CMD cmd
typedef int CHAT_CMD (request_rec *r, char *message_text);
extern const struct cmd_type cmd_table[];
struct cmd_type
{
char *name;
CHAT_CMD *cmd;
int rank;
int room;
};
DECLARE_CHAT_CMD(do_admin);
DECLARE_CHAT_CMD(do_alink);
DECLARE_CHAT_CMD(do_archive);
DECLARE_CHAT_CMD(do_background);
DECLARE_CHAT_CMD(do_bgcolor);
DECLARE_CHAT_CMD(do_boot);
DECLARE_CHAT_CMD(do_bottom);
DECLARE_CHAT_CMD(do_box);
DECLARE_CHAT_CMD(do_bozo);
DECLARE_CHAT_CMD(do_close);
DECLARE_CHAT_CMD(do_color);
DECLARE_CHAT_CMD(do_commands);
#endif /* _COMMAND_H */

Related

The address of a pointer returned by some function gets changed, why? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
Sorry I cannot post any reproducible code as it's part of the code of a large project.
The snippet is
struct res_data *getRes(int id) {
struct res_data *ret = malloc(sizeof(*ret));
/*
* res.aa = getAA(), etc...
*/
// print ret got: 0x55ffb23ce000
fprintf(stderr, "return: ret: %p\n", ret);
return ret;
}
Then
struct res_data *data = getRes(id);
fprintf(stderr, "got: %p\n", data);
// print data got: 0xffffffffb23ce000
Why is that? Any possible cause?
Transferring comments in answer.
Diagnosis
I'd lay odds you've not properly declared getRes() in a header that is used both where it is defined and where it is used, so the place where it is used thinks that it got a 32-bit int from getRes(), which it then sign-extended to create the pointer saved in data.
The last 8 hex digits (B23CE000) are the same in both values, but the original pointer in getRes() had some zero-bits in the leading 4 bytes, but that in the calling code has all bits 1, indicating sign-extension.
Moral: make sure you have accurate prototypes in force. Make your compiler insist on them. Heed its warnings!
Here is some code that reproduces the problem — but it is hair-raising to me. I don't normally publish code like this.
main31.c
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
// Incorrect declaration, but what the compiler infers, more or less
// extern int getRes(int id);
int main(void)
{
struct res_data *data = (struct res_data *)getRes(31);
fprintf(stderr, "%6s: 0x%.16" PRIXPTR "\n", __func__, (uintptr_t)data);
//free(data); // free fails because the pointer is incorrect
return 0;
}
getres31.c
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
struct res_data
{
int id;
char part2[32];
double part3;
};
extern struct res_data *getRes(int id);
struct res_data *getRes(int id)
{
struct res_data *ret = malloc(sizeof(*ret));
ret->id = id;
ret->part2[0] = '\0';
ret->part3 = 0.0;
fprintf(stderr, "%6s: 0x%.16" PRIXPTR "\n", __func__, (uintptr_t)ret);
return ret;
}
This code is essentially clean, except that the declaration of getRes() should be in a header included in both getres31.c and main31.c.
Compilation and running
Normally, I compile with -Werror set so the warnings would cause the compilation to fail.
$ make so-6051-9209-a
gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -c -o main31.o main31.c
main31.c: In function ‘main’:
main31.c:10:48: warning: implicit declaration of function ‘getRes’; did you mean ‘gets’? [-Wimplicit-function-declaration]
10 | struct res_data *data = (struct res_data *)getRes(31);
| ^~~~~~
| gets
main31.c:10:29: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
10 | struct res_data *data = (struct res_data *)getRes(31);
| ^
gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -c -o getres31.o getres31.c
gcc -o so-6051-9219-a -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes main31.o getres31.o
$
When run, the output varies:
$ ./so-6051-9219-a
getRes: 0x00007FDF41D02620
main: 0x0000000041D02620
$ ./so-6051-9219-a
getRes: 0x00007F868AC02AA0
main: 0xFFFFFFFF8AC02AA0
$
Sometimes, the value received in main() is interpreted as positive, sometimes as negative, but the value is sign-extended.
Prescription
The fix is to put the declaration of getRes() into a header, and include that header in both source files.
main37.c
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include "getres37.h"
int main(void)
{
struct res_data *data = getRes(31);
fprintf(stderr, "%6s: 0x%.16" PRIXPTR "\n", __func__, (uintptr_t)data);
free(data);
return 0;
}
Note that it is safe to free the data this time.
getres37.c
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include "getres37.h"
struct res_data
{
int id;
char part2[32];
double part3;
};
struct res_data *getRes(int id)
{
struct res_data *ret = malloc(sizeof(*ret));
ret->id = id;
ret->part2[0] = '\0';
ret->part3 = 0.0;
fprintf(stderr, "%6s: 0x%.16" PRIXPTR "\n", __func__, (uintptr_t)ret);
return ret;
}
getres37.h
#ifndef GETRES37_H_INCLUDED
#define GETRES37_H_INCLUDED
extern struct res_data *getRes(int id);
#endif /* GETRES37_H_INCLUDED */
Compilation and running
$ make so-6051-9219-b
gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -c -o main37.o main37.c
gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -c -o getres37.o getres37.c
gcc -o so-6051-9219-b -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes main37.o getres37.o
$
No warnings!
$ ./so-6051-9219-b
getRes: 0x00007FBA11600700
main: 0x00007FBA11600700
$ ./so-6051-9219-b
getRes: 0x00007FED23C02AA0
main: 0x00007FED23C02AA0
$
This time, there's no problem; the value of the pointer in main() matches the value in getRes().
Note that the header declares an opaque (incomplete) type struct res_data and declares a function that returns a pointer to that type. The main() function cannot dereference the pointer it is returned — it doesn't know (or need to know) the details of the structure. That's hidden in the file containing getRes(). This is the way that C supports information hiding. Using an opaque structure type is much safer than the alternative sometimes seen, which is using void * everywhere. That is dangerous as it provides no type safety, unlike the opaque structure types.
Also note that it was easy to create an MCVE (Minimal, Complete, Verifiable Example)
(or MRE or whatever name SO now uses)
or an
SSCCE (Short, Self-Contained, Correct Example). It really didn't require very much code at all. But it does make life so much easier — we don't have to do the guesswork!
JFTR: Testing on a MacBook Pro running macOS Mojave 10.14.6, using GCC 9.2.0 plus Xcode 11.3.1.
The most likely cause for this surprising behavior is a missing prototype for getRes() when you call this function from main().
Declare the function in a header that you include in both files as
extern struct res_data *getRes(int id);

Error: invalid value 'precompiled-header' in '-x precompiled-header'

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

Use of extern variable in c

I have made two files in c i.e. file1.c file2.c. In file1.c I wrote
#include< stdio.h >
int s=10;
void main()
{
printf("This is file 1");
}
In file2.c
include < stdio.h >
extern int s;
void main() {
printf("%d",s);
}
When I compiled file2.c in ubuntu terminal I got undefined referenced to s error.
How can I resolve this error?
In the second case,
extern int s;
tells the compiler that "somewhere there" exists a variable s which has type int, but it actually does not "define" the variable. So, the linker has no clue where to find the variable, it cannot find the variable and throws the error.
You need to have a definition of the variable, either in a separate translation unit (the purpose of using extern) or in the same translation unit (if you want).
In file1.c
#include <stdio.h>
void myfunction( void );
int s=10;
void myfunction()
{
printf("This is file 1");
}
In file2.c
#include <stdio.h>
void myfunction( void );
extern int s;
int main( void )
{
myfunction();
printf("%d",s);
}
then compile (the example uses gcc
gcc -g -Wall -Wextra -pedantic -Wconversion -std=gnu11 -c file1.c -o file1.o
gcc -g -Wall -Wextra -pedantic -Wconversion -std=gnu11 -c file2.c -o file2.o
then link using:
gcc -g file1.o file2.o -o myexec
then run it as
./myexec
Of course, if your using Visual Studio, the command line statements will be slightly different

gcc: fixing -pedantic "unnamed structure" warning

I'm trying to get some code from elsewhere (specifically, here), to compile without any warnings when gcc is given the -pedantic flag. The only problem is this bit of code:
struct __attribute__ ((aligned(NLMSG_ALIGNTO))) {
struct nlmsghdr nl_hdr;
/* Unnamed struct start. */
struct __attribute__ ((__packed__)) {
struct cn_msg cn_msg;
struct proc_event proc_ev;
};
/* Unnamed struct end. */
} nlcn_msg;
No matter where I try to put in a name for the structure, it results in a compilation error. Is there some way to modify the given code to satisfy -pedantic? Or is there some way to tell gcc to not issues a warning just for that piece of code?
Which standard are you compiling to?
Given this code:
#define NLMSG_ALIGNTO 4
struct nlmsghdr { int x; };
struct cn_msg { int x; };
struct proc_event { int x; };
struct __attribute__ ((aligned(NLMSG_ALIGNTO))) {
struct nlmsghdr nl_hdr;
/* Unnamed struct start. */
struct __attribute__ ((__packed__)) {
struct cn_msg cn_msg;
struct proc_event proc_ev;
};
/* Unnamed struct end. */
} nlcn_msg;
Compiling with C99 mode, I get errors:
$ gcc -O3 -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
-Wold-style-definition -Werror -pedantic -c x2.c
x2.c:13:6: error: ISO C99 doesn’t support unnamed structs/unions [-Werror=pedantic]
};
^
cc1: all warnings being treated as errors
$
Compiling with C11 mode, I get no errors:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
-Wold-style-definition -Werror -pedantic -c x2.c
$

gcc produces warning for qsort

We have some code in spatialite that looks like:
static int cmp_pt_coords (const void *p1, const void *p2)
{
....
}
static gaiaGeomCollPtr auxPolygNodes (gaiaGeomCollPtr geom)
{
....
/* sorting points by coords */
qsort (sorted, count, sizeof (gaiaPointPtr), cmp_pt_coords);
....
}
This is obviously simplified - the real code can be seen at
https://www.gaia-gis.it/fossil/libspatialite/artifact/fe1d6e12c2f98dff23f9df9372afc23f745b50df
The error that I'm getting from gcc (gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3)) is
/bin/bash ../../libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I../.. -g -Wall -Werror -fprofile-arcs -ftest-coverage -g -I../../src/headers -fvisibility=hidden -g -Wall -Werror -fprofile-arcs -ftest-coverage -g -MT libsplite_la-spatialite.lo -MD -MP -MF .deps/libsplite_la-spatialite.Tpo -c -o libsplite_la-spatialite.lo `test -f 'spatialite.c' || echo './'`spatialite.c
libtool: compile: gcc -DHAVE_CONFIG_H -I. -I../.. -g -Wall -Werror -fprofile-arcs -ftest-coverage -g -I../../src/headers -fvisibility=hidden -g -Wall -Werror -fprofile-arcs -ftest-coverage -g -MT libsplite_la-spatialite.lo -MD -MP -MF .deps/libsplite_la-spatialite.Tpo -c spatialite.c -fPIC -DPIC -o .libs/libsplite_la-spatialite.o
spatialite.c: In function 'auxPolygNodes':
spatialite.c:17843:5: error: passing argument 4 of 'qsort' from incompatible pointer type [-Werror]
/usr/include/stdlib.h:761:13: note: expected '__compar_fn_t' but argument is of type 'int (*)(void *, void *)'
cc1: all warnings being treated as errors
I've looked at some previous postings:
What are the parameters in this C qsort function call?
Warning when using qsort in C
However they don't really seem the same (or at least, the way I read the suggestions in those postings is what I think we're already doing here).
I can cast around this, using:
qsort (sorted, count, sizeof (gaiaPointPtr), (__compar_fn_t)cmp_pt_coords);
However I don't see why that should be necessary, and I'm worried about portability to other systems. It seems like the compiler is omitting the const-s from the arguments.
That cast is perfectly fine. GCC isn't smart enough to know that __compar_fn_t is
int (*)(const void *, const void *)
so it issues a warning.
However, __compar_fn_t is not portable -- so if you don't want to use it for casting, you should probably make GCC not warn about this using an appropriate compiler flag.
Or you can see whether __compar_fn_t is defined, and if not, define it yourself:
#ifndef __GNUC__
typedef int (*__compar_fn_t)(const void *, const void *);
#endif
The error probably comes from the visibility flag that you pass to the compiler. Your are saying that all functions in that compilation unit should be hidden. For gcc this changes the function API so your comparison function is then incompatible with the one expected by qsort.
You might want to deal with
#pragma visibility
or
__attribute__((__visibility(default)))
or similar for your comparison function.
The reason for the warning/error is that the GCC prototype of __compar_fn_t is:
typedef int (*__compar_fn_t)(__const void *, __const void );
and not:
typedef int (__compar_fn_t)(const void *, const void *);
Therefore, in order to solve the problem, simply define your function as:
static int cmp_pt_coords (__const void *p1, __const void *p2)

Resources