You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用函数分配复杂自定义数据结构的问题排查

问题解决:指针地址传递后的内存分配与类型转换

你的代码核心问题是直接对void*类型解引用——C语言不允许操作void类型的对象,因为它没有明确的大小,编译器无法确定如何访问其指向的内存。当你传入&ptr(指针的地址)时,实际传递的是「指针的指针」,需要先将void*转换为对应类型的「指针的指针」,才能正确赋值。

具体修改步骤

  1. 修正void*参数的类型转换:
    每个void*参数实际对应不同的「指针的指针」类型,处理前必须先强制转换为目标类型,再解引用赋值。
  2. 修复错误提示的字符串:
    第二个printf错误复用了dist_decharge的提示,应改为对应变量名。
  3. 可选:用具体类型替代void*提升安全性:
    直接使用具体的「指针的指针」类型作为参数,避免强制转换,还能让编译器做类型检查,从根源避免类型错误。

修改后的代码

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <errno.h>

// 假设camion_t是已定义的自定义类型
typedef struct {
    // 自定义字段
} camion_t;

// 假设new_matrix是已实现的矩阵分配函数
int** new_matrix(int m);

int init_structures(void* d_decharge,
                    void* d_poubelles,
                    void* e_camions,
                    int m, int n,
                    int *tamp_id, int* file_msg_id)
{
    // 处理int数组:将void*转为int**,再解引用赋值
    *((int**)d_decharge) = malloc(m * sizeof(int));
    if (*((int**)d_decharge) == NULL){
        printf("echec malloc dist_decharge\n");
        return 1;
    }

    // 处理int矩阵:将void*转为int***,再解引用赋值
    *((int***)d_poubelles) = new_matrix(m);
    if(*((int***)d_poubelles) == NULL){
        printf("echec malloc dist_poubelles\n");
        return 1;
    }

    key_t key_tamp = ftok("./src/main.c", 64);
    int id = shmget(key_tamp, sizeof(camion_t) * n, 0666 | IPC_CREAT);
    if (id == -1){
        printf("echec creation du tampon etats_camions, error[%s]\n", strerror(errno));
        return 1;
    }
    *tamp_id = id;
    // 处理共享内存的camion_t数组:将void*转为camion_t**,再解引用赋值
    *((camion_t**)e_camions) = shmat(*tamp_id, NULL, 0);
    
    key_t key_msg = ftok("./src/main.c", 64);
    id = msgget(key_msg, 0666 | IPC_CREAT);
    if(id==-1){
        printf("echec creation de la file de messages Faffec, error[%s]\n", strerror(errno));
        return 1;
    }
    *file_msg_id = id;
    return 0;
}

更安全的替代方案(不用void*)

如果不需要函数的通用性,直接用具体类型作为参数,完全避免强制转换:

int init_structures(int** d_decharge,
                    int*** d_poubelles,
                    camion_t** e_camions,
                    int m, int n,
                    int *tamp_id, int* file_msg_id)
{
    *d_decharge = malloc(m * sizeof(int));
    if (*d_decharge == NULL){
        printf("echec malloc dist_decharge\n");
        return 1;
    }

    *d_poubelles = new_matrix(m);
    if(*d_poubelles == NULL){
        printf("echec malloc dist_poubelles\n");
        return 1;
    }

    // 后续共享内存处理逻辑不变
    key_t key_tamp = ftok("./src/main.c", 64);
    int id = shmget(key_tamp, sizeof(camion_t) * n, 0666 | IPC_CREAT);
    if (id == -1){
        printf("echec creation du tampon etats_camions, error[%s]\n", strerror(errno));
        return 1;
    }
    *tamp_id = id;
    *e_camions = shmat(*tamp_id, NULL, 0);
    
    key_t key_msg = ftok("./src/main.c", 64);
    id = msgget(key_msg, 0666 | IPC_CREAT);
    if(id==-1){
        printf("echec creation de la file de messages Faffec, error[%s]\n", strerror(errno));
        return 1;
    }
    *file_msg_id = id;
    return 0;
}

调用时直接传入指针的地址:

int* dist_decharge = NULL;
int** dist_poubelles = NULL;
camion_t* etats_camions = NULL;
int tamp_id, msg_id;

init_structures(&dist_decharge, &dist_poubelles, &etats_camions, m, n, &tamp_id, &msg_id);

关键说明

  • 当你传递&ptr时,传递的是指针本身的地址,函数需要用「指针的指针」类型接收,才能修改原指针的值(这不是值传递问题,而是之前用错了参数类型)。
  • void*是通用指针,但只能用来存储地址,不能直接解引用或做算术运算,必须转换为具体类型后才能操作。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 21:28:14