惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 叶小钗
D
Docker
Google DeepMind News
Google DeepMind News
Y
Y Combinator Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Blog — PlanetScale
Blog — PlanetScale
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
U
Unit 42
博客园 - 【当耐特】
N
Netflix TechBlog - Medium
V
Visual Studio Blog
Microsoft Azure Blog
Microsoft Azure Blog
博客园_首页
Recent Announcements
Recent Announcements
GbyAI
GbyAI
T
Tailwind CSS Blog
S
SegmentFault 最新的问题
WordPress大学
WordPress大学
T
The Blog of Author Tim Ferriss
Engineering at Meta
Engineering at Meta
L
LangChain Blog
A
About on SuperTechFans
M
MIT News - Artificial intelligence
B
Blog

博客园 - 寒魔影

Linux waitpid函数分析 不同进程内相同的变量内存地址是相同的 Linux 内存虚拟地址介绍 Sword B树学习笔记二 Sword B树学习笔记一 defined but not used警告屏蔽 apisix流量高峰期服务卡住问题 服务卡死现象分析实录 服务资源加载延迟异常增加 Linux 常用命令四 TCP全连接队列 调用writev收到信号SIGPIPE问题分析记录 epoll_wait监听事件延迟问题记录 writev发送数据失败 C++ new关键字运算符重载 Missing separate debuginfos类型崩溃分析 服务压测偶现卡住问题分析 C语言 数据类型 Linux 终端光标控制函数
宏定义导致数据异常问题
寒魔影 · 2024-01-15 · via 博客园 - 寒魔影
/*
 * Copyright (C) gtc.
 */


#ifndef _GTC_QUEUE_H_INCLUDED_
#define _GTC_QUEUE_H_INCLUDED_

#include "gtc_core.h"


typedef struct gtc_queue_s  gtc_queue_t;

struct gtc_queue_s {
    gtc_queue_t  *prev;
    gtc_queue_t  *next;
};


#define gtc_queue_init(q)                                                     \
    (q)->prev = q;                                                            \
    (q)->next = q


#define gtc_queue_empty(h)                                                    \
    (h == (h)->prev)


#define gtc_queue_push(h, x)                                                  \
    (x)->next = (h)->next;                                                    \
    (x)->next->prev = x;                                                      \
    (x)->prev = h;                                                            \
    (h)->next = x


#define gtc_queue_tail(h)                                                     \
    (h)->prev


#define gtc_queue_remove(x)                                                   \
    (x)->next->prev = (x)->prev;                                              \
    (x)->prev->next = (x)->next


#define gtc_queue_pop(h)                                                      \
    gtc_queue_remove(h->prev)                                              


#define gtc_queue_data(q, type, link)                                         \
    (type *) ((u_char *) q - offsetof(type, link))


#endif /* _GTC_QUEUE_H_INCLUDED_ */

上述是一个队列的实现,这个队列实现是有问题的,问题在于 gtc_queue_pop 这个宏定义。
宏定义本质上是一种替换,gtc_queue_pop 中调用了 gtc_queue_remove ,这里的传参有讲究,
gtc_queue_remove 的入参是 h->prev,当执行 gtc_queue_remove 中 (x)->next->prev = (x)->prev; 语句时
会导致 h->prev 的指向发生了变化,导致下面的执行出现异常,宏不同于函数,它的简单替换可能会带来一些奇怪的问题
特此做好记录。