【问题标题】:How to fix allocated memory from a struct hack in a different method?如何以不同的方法从 struct hack 修复分配的内存?
【发布时间】:2017-01-20 13:09:19
【问题描述】:

我正在用 C 语言开发用于通信的驱动程序,并且交换的消息没有固定大小。通信总线的推荐是多主题使用structs,我也是这样。

我的第一个问题:我必须继续收听新消息,当我收到一条消息时,我必须处理消息数据(它有延迟)并仍在收听新消息。

第一种解决方案:收到新消息时使用线程处理数据。

我的第二个问题:消息中的数据可以有一个结构的多个数据,而我的通信器需要使用一个结构来组织这些多个值。

第二个解决方案:使用struct hack分配struct的内存动态大小。

我当前的问题:当我将结构作为参数传递给线程或任何函数时,我会丢失数据结构并得到错误的值。

一个简短的测试是:

typedef struct test{
    int size;
    int value[];
} test;

void allocation(test *v){
    test *aux = (test *)malloc(sizeof(test)+3*sizeof(int));
    int i;
    aux->value[0] = 2;
    aux->size = 3;
    aux->value[1] = 1;
    aux->value[2] = 5;
    printf("Teste1 %d\n",aux->size);
    for(i=0; i < aux->size; i++){
        printf("%d\n", aux->value[i]);
    }
    *v = *aux;
}

void cleanup(test *v){
    free(v);
}

int main(int argc, char *argv[]){
    test v;
    int i;

    allocation(&v);
    printf("Teste2 %d\n",v.size);
    for(i=0; i < v.size; i++){
        printf("%d\n", v.value[i]);
    }
    //cleanup(&v);
    return 0;
}

在这个测试中,我在第一次打印时得到了正确的值,在第二次打印时得到了错误的值(只有 v.size 给出了正确的值)。

而且我的结构比测试中的结构要复杂一些。我的结构是这样的:

typedef struct test1{
    double v1;
    double v2;
} test1;

typedef struct test2{
    int size;
    test1 values[];
} test2;

一旦我拥有了所有需要修复的元素,你知道如何在该函数中修复我的内存结构吗?请记住,我还可以分配多个 test2 数据是可取的(不是必需的)。

【问题讨论】:

  • 请注意,在结构末尾使用[]灵活数组成员 (FAM),C99 及更高版本完全支持。 'struct hack' 使用 [1] 而不是 [] 并且不受完全支持(尽管它通常可以工作,尤其是因为在引入 FAM 之前它是必要的,并且仍然需要保持工作代码的向后兼容性)。

标签: c struct dynamic-allocation


【解决方案1】:

这里的事情是你分配了不完整成员int value[]的结构;虽然原则上可以按值复制两个结构(如果你写*v = *aux,实际上会发生这种情况);但是,由于编译器不知道 value[] 在运行时将采用哪个大小成员,v 的“sizeof”以及 *aux 的大小始终为 4,即一个 int 成员的已知大小size。因此,只有 this 被复制,而 value[]-array 根本不会被复制。

解决这种情况的方法是需要一个指向指针的指针(即allocation(test **v),这样保留的内存可以直接分配给它,使用main中的struct test指针,即test *vptr,以及致电allocation(&amp;vptr)

如果您无法避免传递对值的尊重(而不是对指向值的指针的引用),我想您将不得不使用memcpy 来传输内容。但这实际上没有意义,因为接收者必须提前提供足够的空间来接收value[]-array(如果您简单地声明test v 形式的变量,则情况并非如此)。然后mallocaux 没有意义;您可以直接写入通过引用传递的对象v

【讨论】:

    【解决方案2】:

    您将v 声明为非指针,这意味着当您在main 中声明它时,已经为v 分配了内存。发送对allocation 的引用只会正确复制size,因为它不是动态分配的。正确的做法是:

    • v 声明为指针

    • 让你的allocation返回test* (test* allocation())

    • 将它分配给main 中的v。即类似v = allocate()

    • 从此以后像指针一样使用v

    编辑:由于 OP 希望它仅用作参数,因此最好的方法是使用双指针。检查以下代码:

    typedef struct test{
        int size;
        int value[];
    } test;
    
    void allocation(test **v){
        test *aux = (test *)malloc(sizeof(test)+3*sizeof(int));
        int i;
        aux->value[0] = 2;
        aux->size = 3;
        aux->value[1] = 1;
        aux->value[2] = 5;
        printf("Teste1 %d\n",aux->size);
        for(i=0; i < aux->size; i++){
            printf("%d\n", aux->value[i]);
        }
        *v = aux;
    }
    
    void cleanup(test *v){
        free(v);
    }
    
    int main(int argc, char *argv[]){
        test **v;
        v = malloc (sizeof (test*));
        int i;
    
        allocation(v);
        printf("Teste2 %d\n",(*v)->size);
        for(i=0; i < (*v)->size; i++){
            printf("%d\n", (*v)->value[i]);
        }
        //cleanup(&v);
        return 0;
    }
    

    请注意,此后您的清理工作也会发生变化。

    【讨论】:

    • 你的答案确实可以解决测试,但我不能在线程中使用它,一旦创建线程我们将函数和结构地址作为参数传递,我仍然必须使用参数来解决这个问题.你知道另一种解决方案吗?
    • 是的,您可以使用双指针,查看我编辑的答案中的工作代码。你必须根据你的设置稍微调整一下。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-02
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    相关资源
    最近更新 更多