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

推荐订阅源

Apple Machine Learning Research
Apple Machine Learning Research
Y
Y Combinator Blog
博客园 - 【当耐特】
V
Visual Studio Blog
GbyAI
GbyAI
V
V2EX
P
Proofpoint News Feed
Microsoft Azure Blog
Microsoft Azure Blog
Microsoft Security Blog
Microsoft Security Blog
D
DataBreaches.Net
Hugging Face - Blog
Hugging Face - Blog
A
About on SuperTechFans
The Cloudflare Blog
阮一峰的网络日志
阮一峰的网络日志
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
N
Netflix TechBlog - Medium
aimingoo的专栏
aimingoo的专栏
B
Blog RSS Feed
量子位
MongoDB | Blog
MongoDB | Blog
有赞技术团队
有赞技术团队
人人都是产品经理
人人都是产品经理
Stack Overflow Blog
Stack Overflow 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 的指向发生了变化,导致下面的执行出现异常,宏不同于函数,它的简单替换可能会带来一些奇怪的问题
特此做好记录。