我遇到嵌套结构及其专用复制功能的问题。类型的结构如下:
Data
个实例Problem
实例都包含指向Data
实例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建议在prob
中释放free_bigproblem
变量时会出现问题,但如果正确复制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)
非常感谢任何帮助。
答案 0 :(得分:1)
我做了一些小改动 想想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;
}