gpt4 book ai didi

c - C 中嵌套结构类型和复制函数的内存泄漏

转载 作者:行者123 更新时间:2023-11-30 15:23:33 26 4
gpt4 key购买 nike

我对嵌套结构及其专用复制函数有疑问。类型的结构如下:

  1. 程序中有一个 Data 实例
  2. 每个 Problem 实例都包含一个指向 Data 实例的指针
  3. 每个 Bigproblem 实例都有其自己的 Problem 实例。

因此,当复制 BigProblem 实例时,也会创建 Problem 实例的副本。代码如下:

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

// types

struct Data {
int n;
int *x;
};
typedef struct Data data_t;

struct Problem {
data_t *data;
int m;
int *y;
};
typedef struct Problem problem_t;

struct BigProblem {
problem_t *prob;
int p;
int *z;
};
typedef struct BigProblem big_t;

// functions

data_t init_data(int s)
{
data_t dat;
dat.n = s;
dat.x = calloc(s, sizeof(int));
return dat;
}

problem_t init_problem(data_t *dat)
{
problem_t prob;
prob.data = dat;
prob.m = 5;
prob.y = calloc(prob.data->n, sizeof(int));
return prob;
}

problem_t copy_problem(problem_t *prob)
{
int i;
problem_t probc;
probc.data = prob->data;
probc.m = prob->m;
probc.y = calloc(prob->data->n, sizeof(int));
for (i=0; i<prob->data->n; i++)
probc.y[i] = prob->y[i];
return probc;
}

big_t init_bigproblem(problem_t *prob)
{
big_t bigprob;
bigprob.prob = prob;
bigprob.p = 3;
bigprob.z = calloc(prob->m, sizeof(int));
return bigprob;
}

big_t copy_bigproblem(big_t *bigprob)
{
int i;
big_t bigprobc;
problem_t probc = copy_problem(bigprob->prob);
bigprobc.prob = &probc;
bigprobc.p = bigprob->p;
bigprobc.z = calloc(bigprob->prob->m, sizeof(int));
for (i=0; i<bigprob->prob->m; i++)
bigprobc.z[i] = bigprob->z[i];
return bigprobc;
}

void free_data(data_t *dat)
{
free(dat->x);
}

void free_problem(problem_t *prob)
{
free(prob->y);
}

void free_bigproblem(big_t *bigprob)
{
free(bigprob->z);
free_problem(bigprob->prob);
}

int main(int argc, char **argv)
{
data_t mydata = init_data(10);
problem_t myproblem = init_problem(&mydata);
big_t mybigprob = init_bigproblem(&myproblem);

big_t big_copy = copy_bigproblem(&mybigprob);

free_bigproblem(&mybigprob);
free_bigproblem(&big_copy);
free_data(&mydata);

return 0;
}

我怀疑问题与copy_bigproblem中的这些行有关:

    problem_t probc = copy_problem(bigprob->prob);
bigprobc.prob = &probc;

但我无法准确指出这里出了什么问题。 Valgrind 表明问题发生在释放 free_bigproblem 中的 prob 变量时,但如果正确复制了 Problem 实例,则不会发生这种情况。 Valgrind 输出在这里:

==10384== Memcheck, a memory error detector
==10384== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==10384== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==10384== Command: ./typedeftest
==10384==
==10384== Conditional jump or move depends on uninitialised value(s)
==10384== at 0x4C2B1B6: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10384== by 0x4007D4: free_problem (typedeftest.c:97)
==10384== by 0x400801: free_bigproblem (typedeftest.c:103)
==10384== by 0x400879: main (typedeftest.c:115)
==10384== Uninitialised value was created by a stack allocation
==10384== at 0x4007B9: free_problem (typedeftest.c:96)
==10384==
==10384== Invalid free() / delete / delete[] / realloc()
==10384== at 0x4C2B200: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10384== by 0x4007D4: free_problem (typedeftest.c:97)
==10384== by 0x400801: free_bigproblem (typedeftest.c:103)
==10384== by 0x400879: main (typedeftest.c:115)
==10384== Address 0x400f610 is in the Text segment of /usr/lib/ld-2.21.so
==10384== at 0x400F610: _dl_fini (in /usr/lib/ld-2.21.so)
==10384==
==10384==
==10384== HEAP SUMMARY:
==10384== in use at exit: 40 bytes in 1 blocks
==10384== total heap usage: 5 allocs, 5 frees, 160 bytes allocated
==10384==
==10384== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==10384== at 0x4C2C080: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10384== by 0x40061A: copy_problem (typedeftest.c:58)
==10384== by 0x400704: copy_bigproblem (typedeftest.c:81)
==10384== by 0x400861: main (typedeftest.c:112)
==10384==
==10384== LEAK SUMMARY:
==10384== definitely lost: 40 bytes in 1 blocks
==10384== indirectly lost: 0 bytes in 0 blocks
==10384== possibly lost: 0 bytes in 0 blocks
==10384== still reachable: 0 bytes in 0 blocks
==10384== suppressed: 0 bytes in 0 blocks
==10384==
==10384== For counts of detected and suppressed errors, rerun with: -v
==10384== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)

任何帮助将不胜感激。

最佳答案

我做了一些小改动考虑 memcpy 而不是循环

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

// types

struct Data {
int n;
int *x;
};
typedef struct Data data_t;

struct Problem {
data_t *data;
int m;
int *y;
};
typedef struct Problem problem_t;

struct BigProblem {
problem_t prob;
int p;
int *z;
};
typedef struct BigProblem big_t;

// functions

void init_data(data_t *dat, int s)
{
dat->n = s;
dat->x = calloc(s, sizeof(int));
}

void init_problem(problem_t *prob, data_t *dat)
{
prob->data = dat;
prob->m = 5;
prob->y = calloc(prob->data->n, sizeof(int));
}

void init_bigproblem(big_t *bigprob, problem_t *prob)
{
bigprob->prob = *prob;
bigprob->p = 3;
bigprob->z = calloc(prob->m, sizeof(int));
}

copy_problem(problem_t *src, problem_t *cpy)
{
int i;
cpy->data = src->data;
cpy->m = src->m;
cpy->y = calloc(src->data->n, sizeof(int));
for (i=0; i<src->data->n; i++)
cpy->y[i] = src->y[i];
}

void copy_bigproblem(big_t *src, big_t *cpy)
{
int i;

copy_problem(&src->prob, &cpy->prob);
cpy->p = src->p;
cpy->z = calloc(src->prob.m, sizeof(int));
for (i=0; i<src->prob.m; i++)
cpy->z[i] = src->z[i];
}

void free_data(data_t *dat)
{
free(dat->x);
}

void free_problem(problem_t *prob)
{
free(prob->y);
}

void free_bigproblem(big_t *bigprob)
{
free(bigprob->z);
free_problem(&bigprob->prob);
}

int main(int argc, char **argv)
{
data_t mydata;
problem_t myproblem;
big_t mybigprob, big_copy;

init_data(&mydata, 10);
init_problem(&myproblem, &mydata);
init_bigproblem(&mybigprob, &myproblem);

copy_bigproblem(&mybigprob, &big_copy);


free_bigproblem(&mybigprob);
free_bigproblem(&big_copy);
free_data(&mydata);

return 0;
}

关于c - C 中嵌套结构类型和复制函数的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28764575/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com