Я компилировал некоторый код, который ранее компилировался (с теми же параметрами), и после некоторых несвязанных изменений компоновщик начал находить переменную, которая может быть неинициализирована (я подозреваю, что эти несвязанные изменения могут помешать g cc). алгоритм оптимизации и может вызвать ошибку).
Система:
- debian 11 (тестирование)
- linux 5.4.0-4-amd64
- g cc 9.2.1 (Debian 9.2.1-29)
- как 2.34
- ld 2.34
Я использую следующие оптимизации:
-O3 -flto -fuse-linker-plugin -march=native -static
Программа пытается установить tcp-сервер, и сокет является, возможно, неинициализированной переменной.
libalx/base/socket/tcp/server.c
:
#include "libalx/base/socket/tcp/server.h"
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
static
int get_addrs (const char *server_port, struct addrinfo **addrs);
static
int set_server (int sd, int *optval, struct addrinfo *ad, int backlog);
static
int set_socket (struct addrinfo *addrs, int backlog);
int tcp_server_open (const char *server_port, int backlog)
{
int sd;
struct addrinfo *addrs;
sd = -1;
if (get_addrs(server_port, &addrs))
return -1;
sd = set_socket(addrs, backlog);
freeaddrinfo(addrs);
if (sd < 0)
return -2;
return sd;
}
static
int get_addrs (const char *server_port, struct addrinfo **addrs)
{
struct protoent *tcp;
struct addrinfo hint = {0};
tcp = getprotobyname("tcp");
if (!tcp)
return -1;
hint.ai_family = AF_UNSPEC;
hint.ai_socktype = SOCK_STREAM;
hint.ai_protocol = tcp->p_proto;
hint.ai_flags = AI_PASSIVE;
if (getaddrinfo(NULL, server_port, &hint, addrs))
return -1;
return 0;
}
static
int set_socket (struct addrinfo *addrs, int backlog)
{
int val;
int sock;
sock = -1;
for (struct addrinfo *ad = addrs; ad; ad = ad->ai_next) {
sock = socket(ad->ai_family, ad->ai_socktype, ad->ai_protocol);
if (sock < 0)
continue;
if (!set_server(sock, &val, ad, backlog))
break;
close(sock);
sock = -1;
}
return sock;
}
static
int set_server (int sd, int *optval, struct addrinfo *ad, int backlog)
{
*optval = 1;
if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, optval, sizeof(*optval)))
return -1;
if (bind(sd, ad->ai_addr, ad->ai_addrlen))
return -1;
if (listen(sd, backlog))
return -1;
return 0;
}
libalx/base/linux/membarrier.h
:
#include <unistd.h>
#include <sys/syscall.h>
inline
int membarrier (int cmd, int flags)
{
return syscall(__NR_membarrier, cmd, flags);
}
main.c
:
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <linux/membarrier.h>
#define ALX_NO_PREFIX
#include <libalx/base/compiler/size.h>
#include <libalx/base/linux/membarrier.h>
#include <libalx/base/socket/tcp/server.h>
static int mb_cmd;
static sig_atomic_t sigterm;
static int tcp;
static
int rob_init (void);
static
int rob_deinit (void);
static
int tcp_init (void);
static
int tcp_deinit (void);
static
void cam_session (int cam);
static
int mb_init (void);
static
int sigterm_init (void);
static
void sigterm_handler (int sig);
int main (void)
{
int tcp;
int cam;
struct sockaddr_storage cam_addr = {0};
socklen_t cam_addr_len;
int status;
status = 1;
if (rob_init())
goto out0;
status++;
cam_addr_len = sizeof(cam_addr);
do {
cam = accept(tcp, (struct sockaddr *)&cam_addr, &cam_addr_len);
if (cam < 0) {
goto retry;
}
cam_session(cam);
close(cam);
retry:
asm volatile ("" : : : "memory");
} while (!sigterm);
status = EXIT_SUCCESS;
if (rob_deinit())
status += 32;
out0:
fprintf(stderr, "rob: ERROR: main(): %i\n", status);
return status;
}
static
int rob_init (void)
{
int status;
status = -1;
if (sigterm_init())
goto err;
status--;
if (tcp_init())
goto err;
return 0;
err:
fprintf(stderr, "rob: ERROR: rob_init(): %i\n", status);
return status;
}
static
int rob_deinit (void)
{
int status;
status = 0;
if (tcp_deinit())
status--;
return status;
}
static
int tcp_init (void)
{
tcp = -1;
tcp = tcp_server_open("23", 10);
return tcp < 0;
}
static
int tcp_deinit (void)
{
return close(tcp);
}
static
void cam_session (int cam)
{
static int i = 0;
char cam_data[BUFSIZ];
ssize_t n;
i++;
while (true) {
n = read(cam, cam_data, ARRAY_SIZE(cam_data) - 1);
if (n < 0)
return;
cam_data[n] = 0;
if (!n)
return;
printf("%s\n", cam_data);
}
}
static
int mb_init (void)
{
static bool done = false;
int cmd;
if (done)
return 0;
cmd = membarrier(MEMBARRIER_CMD_QUERY, 0);
if (cmd < 0)
return -2;
if (cmd & MEMBARRIER_CMD_PRIVATE_EXPEDITED) {
mb_cmd = MEMBARRIER_CMD_PRIVATE_EXPEDITED;
if (membarrier(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, 0))
return -3;
} else if (cmd & MEMBARRIER_CMD_GLOBAL_EXPEDITED) {
mb_cmd = MEMBARRIER_CMD_GLOBAL_EXPEDITED;
if (membarrier(MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED, 0))
return -4;
} else {
mb_cmd = MEMBARRIER_CMD_GLOBAL;
}
done = true;
return membarrier(mb_cmd, 0);
}
static
int sigterm_init (void)
{
struct sigaction sa = {0};
if (mb_init())
return -1;
sigterm = false;
membarrier(mb_cmd, 0);
sigemptyset(&sa.sa_mask);
sa.sa_handler = &sigterm_handler;
if (sigaction(SIGTERM, &sa, NULL))
return -3;
return 0;
}
static
void sigterm_handler (int sig)
{
(void)sig;
sigterm = true;
membarrier(mb_cmd, 0);
}
Я попытался отследить источник неинициализированной переменной, но не нашел ничего на 100% прозрачным. Я пропускаю какой-то путь в своем коде, или, может быть, есть какой-то ошибочный путь в socket()
? socket()
- единственный источник, который я не контролирую, и, возможно, его установка не инициализирована.
ошибки:
$ make
gcc -Wall -Wextra -Werror -Wno-implicit-fallthrough -O3 -march=native -flto -fuse-linker-plugin -static `pkg-config --static --cflags libalx-base libalx-telnet-tcp` \
rob.c -o rob \
`pkg-config --static --libs libalx-telnet-tcp libalx-base`
rob.c: In function ‘main’:
rob.c:66:9: error: ‘tcp’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
66 | cam = accept(tcp, (struct sockaddr *)&cam_addr, &cam_addr_len);
| ^
rob.c:53:8: note: ‘tcp’ was declared here
53 | int tcp;
| ^
lto1: all warnings being treated as errors
lto-wrapper: fatal error: gcc returned 1 exit status
compilation terminated.
/usr/bin/ld: error: lto-wrapper failed
collect2: error: ld returned 1 exit status
make: *** [Makefile:9: rob] Error 1