C 链接器抱怨可能未初始化变量(完全优化的构建选项)
我正在编译一些以前编译过的代码(使用相同的选项),在一些不相关的更改之后,链接器开始查找可能未初始化的变量(我怀疑这些不相关的更改可能会干扰gcc的优化算法,并可能触发错误) 系统:C 链接器抱怨可能未初始化变量(完全优化的构建选项),c,linux,sockets,gcc,lto,C,Linux,Sockets,Gcc,Lto,我正在编译一些以前编译过的代码(使用相同的选项),在一些不相关的更改之后,链接器开始查找可能未初始化的变量(我怀疑这些不相关的更改可能会干扰gcc的优化算法,并可能触发错误) 系统: debian 11(测试) linux 5.4.0-4-amd64 gcc 9.2.1(Debian 9.2.1-29) as 2.34 ld 2.34 我使用以下优化: -O3 -flto -fuse-linker-plugin -march=native -static 程序尝试设置tcp服务器,套接字可
- debian 11(测试)
- linux 5.4.0-4-amd64
- gcc 9.2.1(Debian 9.2.1-29)
- as 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;
}
#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);
}
main.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;
}
#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);
}
您有一个名为
tcp
的文件范围变量和一个名为tcp
的局部变量。这真是个坏主意。@user3386109哦,嘘**。我没看见。当我把它改成全球的时候,我应该把它删除。哈哈,是的。在这些事情上必须小心:)仔细观察输出,我认为编译器确实发现了问题。输出状态为“gcc返回1退出状态”。但无论如何都调用了链接器,您也得到了一个“ld returned 1 exit status”。@error path中的user3629249代码是正确的,不是吗?如果发生错误,我将返回一个负套接字,这意味着无法使用该套接字。该函数(也是me)的用户在使用套接字之前检查它是否为非负。您有一个名为tcp
的文件范围变量和一个名为tcp
的局部变量。这真是个坏主意。@user3386109哦,嘘**。我没看见。当我把它改成全球的时候,我应该把它删除。哈哈,是的。在这些事情上必须小心:)仔细观察输出,我认为编译器确实发现了问题。输出状态为“gcc返回1退出状态”。但无论如何都调用了链接器,您也得到了一个“ld returned 1 exit status”。@error path中的user3629249代码是正确的,不是吗?如果发生错误,我将返回一个负套接字,这意味着无法使用该套接字。该函数(也是me)的用户在使用套接字之前检查它是否为非负。