MSVC v142下保存多个va_list时旧实例被覆盖的问题求解
保存多个va_list避免被覆盖的解决方案(MSVC v142环境)
问题背景
在MSVC v142环境下,尝试保存多个va_list并以数组形式传入其他API时,旧的va_list会被新创建的实例覆盖。
初始测试代码
void toVaList(va_list *out, int count, ...) { va_list args; va_start(args, count); vprintf("toVaList: %d %d\n", args); *out = args; } int main() { va_list args1; toVaList(&args1, 2, 11, 22); vprintf("first va_list: %d %d\n", args1); va_list args2; toVaList(&args2, 2, 33, 44); vprintf("first va_list: %d %d\n", args1); // args1已被覆盖 vprintf("second va_list: %d %d\n", args2); va_end(args1); va_end(args2); return 0; }
初始代码运行输出
toVaList: 11 22 first va_list: 11 22 toVaList: 33 44 first va_list: 33 44 second va_list: 33 44
解决方案:使用memcpy复制va_list到独立内存
将va_list复制到独立的内存缓冲区中,避免多个实例互相覆盖。需注意在函数体内用va_start和va_end包裹原va_list,外部使用复制后的缓冲区即可正常工作。
修正后的测试代码
void toVaList1(va_list *out, int count, ...) { va_list args; va_start(args, count); memcpy(out, args, 256); vprintf("toVaList1: %d %d\n", args); va_end(args); } int main() { char args1[256]; toVaList1((va_list *)args1, 2, 11, 22); vprintf("first va_list: %d %d\n", args1); char args2[256]; toVaList1((va_list *)args2, 2, 33, 44); vprintf("first va_list: %d %d\n", args1); vprintf("second va_list: %d %d\n", args2); char args3[256]; toVaList1((va_list *)args3, 2, 55, 66); vprintf("first va_list: %d %d\n", args1); vprintf("second va_list: %d %d\n", args2); vprintf("third va_list: %d %d\n", args3); }
修正后代码运行输出
toVaList1: 11 22 first va_list: 11 22 toVaList1: 33 44 first va_list: 11 22 second va_list: 33 44 toVaList1: 55 66 first va_list: 11 22 second va_list: 33 44 third va_list: 55 66
实际应用场景:批量消息打印API
现有基于XML定义的消息ID系统,以及接收msgId和va_list的内部打印API:
消息定义与内部API
ID Message 1 这是一条包含整数%d和字符串%s的消息。 2 这是另一条包含浮点数%f的消息。 .....
void internalAPI_PrintMsg(int msgId, va_list ap) { char resultMsg[512]; // 根据msgId从XML查找消息并替换参数 // 遍历消息内容的逻辑... switch(char) { case 'd': int i = va_arg(ap, int); // 替换整数参数 break; case 'f': double d = va_arg(ap, double); // 替换浮点数参数 break; .... } PrintResultMessage(resultMsg); }
已实现的单消息打印API
void printMsg(int msgId, ...) { va_list args; va_start(args, msgId); internalAPI_PrintMsg(msgId, args); va_end(args); }
新需求:批量消息打印API
通过结构体存储消息ID和复制后的参数缓冲区,实现批量打印:
typedef struct { long id; char args[256]; } msgData; void printGroupMsg(msgData * msgArr, int msgCount) // 处理多个va_list的新API { // 批量消息初始化操作 for (int i = 0; i < msgCount; ++i) internalAPI_PrintMsg(msgArr[i].id, (va_list)msgArr[i].args); // 批量消息收尾操作 } void initMsgData(msgData *msg, int msgId, ...) // 等价于之前的toVaList { msg->id = msgId; va_list args; va_start(args, msgId); memcpy(msg->args, args, 256); va_end(args); } // 客户端调用示例 msgData *arr = malloc(sizeof(msgData)*2); initMsgData(arr, 1, 88, "test"); initMsgData(arr+1, 2, 123.456); printGroupMsg(arr, 2);
内容的提问来源于stack exchange,提问作者DF24
相关产品推荐
相关产品推荐

