C 语言的函数装饰器-仿函数 设计与实现
程序在现场运行,发生了一系列的崩溃, 定位在 rte_mempool_get/rte_mempool_put和 enqueue_msg/dequeue_msg.
需要盘查 rte_mempool_get/rte_mempool_put 内存节点在各个线程之间来回穿梭,
当 rte_mempool_get 获取成功之后 enqueue入队列马上再 rte_mempool_put 释放,
一定会导致 dequeue 出队列的一方持有了一个野指针对象, 会发生一系列的莫名其妙的崩溃.
那么现在 盘查出 到底是哪里 发生了 上面这种场景.
低压力不能触发崩溃, 需要高压力才能触发.
整个项目中, 充斥着大量的, 诸如这类的代码,将近有70多个文件中
很明显, 直接改每个源文件,是最拙劣的方法!
1 |
|
提示:
如果我在 rte_mempool_put/rte_mempool_put 函数里面修改, 就得不到 调用者的文件名/行号信息
实现 仿函数1
2
3/usr/local/include/dpdk/rte_mempool.h
#define rte_mempool_get_debug(a,b) ({int rc=rte_mempool_get(a,b);printf("get obj %p %s:%u\n",*b,__FILE__,__LINE__);rc;})
#define rte_mempool_put_debug(a,b) ({rte_mempool_put(a,b);printf("put obj %p %s:%u\n",b,__FILE__,__LINE__);})
原始代码:获取1
2
3
4
5
6{
if (rte_mempool_get(tbl_log_mempool, (void **)&obj_new) < 0)
{
return PKT_OK;
}
}
原始代码:释放(注意if语句没有花括号)1
2
3
4
5{
if (write_tbl_log(obj_new) != 1)
rte_mempool_put(obj_mempool, (void *)obj_new);
return;
}
一顿操作:1
2sed -i 's@\brte_mempool_get\b@rte_mempool_get_debug@g' `grep -inrwl rte_mempool_get`
sed -i 's@\brte_mempool_put\b@rte_mempool_put_debug@g' `grep -inrwl rte_mempool_put`
恢复代码1
2sed -i 's@\brte_mempool_get_debug\b@rte_mempool_get@g' `grep -inrwl rte_mempool_get_debug`
sed -i 's@\brte_mempool_put_debug\b@rte_mempool_put@g' `grep -inrwl rte_mempool_put_debug`
新的代码:获取1
2
3
4
5
6{
if (({int rc=rte_mempool_get(tbl_log_mempool,(void **)&obj_new);printf("get obj %p %s:%u\n",*(void **)&obj_new,"xxx.c",283);rc;}) < 0)
{
return PKT_OK;
}
}
新的代码:释放(注意if语句没有花括号)1
2
3
4
5{
if (write_tbl_log(obj_new) != 1)
({rte_mempool_put(obj_mempool,(void *)obj_new); printf("put obj %p %s:%u\n", (void *)obj_new, "xxx.c", 433);});
return;
}
参考: list.h1
#define container_of(ptr, type, member) ({const typeof(((type*)0)->member)*__mptr=(ptr);(type*)((char*)__mptr-offsetof(type,member));})