You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

C语言中使用void指针的可变参数函数出现异常行为的问题求助

问题分析与修复方案

咱们先拆解你代码里的几个关键问题,这些问题叠加起来直接导致了输出为空的异常:

1. 完全错误的循环条件

你写的while(&objPtr[i])是核心bug!这里的objPtr是传入的&myJob(也就是job_t*转成的void*),而void类型没有明确的内存大小,编译器根本不知道objPtr[i]应该跳过多少内存,这属于未定义行为。更关键的是,这个条件和可变参数列表完全无关——你本来是想遍历可变参数,但这个循环实际是在访问myJob结构体后面的内存,完全偏离了目标。

正确的思路是:依赖你代码里提到的NULL终止标记,去掉错误的while循环,换成无限循环直到读到NULL为止。

2. 函数指针赋值的冗余操作

你写的symbolTable.funcOne = *job_create;没必要加*,函数名本身就是函数指针,直接写成symbolTable.funcOne = job_create;就可以了。这个问题不会直接导致输出为空,但属于不必要的冗余写法。

3. 可变参数缺少终止符

你的四次调用都没有在最后传入NULL,比如第一个调用symbolTable.funcOne(&myJob, "hey1", ..., "hey8");没有NULL结尾,那么va_arg会一直读取栈里的垃圾数据,直到碰巧读到NULL,这会导致不可预测的行为。


修复后的代码示例

修改后的job_create函数

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

int job_create(void* objPtr, ...) {
    int i = 0;
    va_list args;
    va_start(args, objPtr);
    // 换成无限循环,依赖NULL终止可变参数遍历
    for (;;) {
        void* arg = va_arg(args, void*);
        if (arg == NULL) {
            break;
        }
        // 显式转换为char*,让printf的%s格式更严谨
        printf("arg %u: %s\n\n", i, (char*)arg);
        i++;
    }
    va_end(args);
    return EXIT_SUCCESS;
}

修改后的main调用部分

typedef struct {
    char* name;
} job_t;

typedef struct {
    int (*funcOne) (void*, ...);
} symbols_t;

int main(void) {
    symbols_t symbolTable;
    symbolTable.funcOne = job_create; // 去掉多余的*
    job_t myJob;
    // 每个调用最后都加上NULL作为终止符
    symbolTable.funcOne(&myJob, "hey1", "hey2", "hey3", "hey4", "hey5", "hey6", "hey7", "hey8", NULL);
    symbolTable.funcOne(&myJob, "hey1", "hey2", NULL);
    symbolTable.funcOne(&myJob, "hey1", NULL);
    symbolTable.funcOne(&myJob, NULL); // 即使无额外参数,也要传NULL终止
    return EXIT_SUCCESS;
}

额外说明

  • 关于void*的使用:在printf里用%s时,最好把void*显式转成char*,虽然大多数编译器允许直接传void*,但显式转换更严谨,能避免潜在的类型匹配问题。
  • 可变参数的安全原则:一定要明确终止条件——要么提前约定参数个数,要么用特殊标记(比如这里的NULL),否则会触发栈溢出或读取垃圾数据的未定义行为。

内容的提问来源于stack exchange,提问作者Garrett

火山引擎 最新活动