我有一个代码创建一个可以是不同类型的值的链接列表,例如弦乐或双打。但是,在程序结束时,在释放链表之后,由于我在其中添加字符串的方式,我留下了内存泄漏。我的代码如下:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// compile with: gcc test_list.c -o test_list
// to check memory leaks run:
// >> valgrind --leak-check=full -v ./test_list
typedef enum tagParamType {
TYPE_double_t = 0,
TYPE_string_t
} ParamType;
size_t TypeSize[2] = {
sizeof(double),
sizeof(const char*)
};
typedef struct tagParam {
char name[1024]; /* Parameter name */
void *value; /* Parameter value */
ParamType type; /* type of parameter */
struct tagParam *next;
} Param;
typedef struct tagParameters {
Param *head;
} Parameters;
void AddParam( Parameters *pars, const char *name, const void *value, ParamType type );
void RemoveParameters( Parameters *pars );
Parameters *CreateParameters( );
void PrintParameters( Parameters *pars );
void AddParam( Parameters *pars, const char *name, const void *value, ParamType type ){
Param *par = NULL;
par = malloc(sizeof(Param));
memset(par, 0, sizeof(Param)); // set everything to 0
par->value = (void *)malloc( TypeSize[type] );
memcpy( par->value, value, TypeSize[type] );
strncpy( par->name, name, 1024 );
par->type = type;
par->next = pars->head;
pars->head = par;
}
void RemoveParameters( Parameters *pars ){
Param *this, *next = NULL;
this = pars->head;
if ( this ) { next = this->next; }
while ( this ){
free( this->value );
free( this );
this = next;
if ( this ) { next = this->next; }
}
pars->head = NULL;
}
Parameters *CreateParameters( ){
Parameters *pars = calloc(sizeof(*pars), 1);
/* add a string */
const char *svalue = strdup("Matthew");
AddParam( pars, "First name", &svalue, TYPE_string_t );
/* add a double */
double dvalue = 0.1;
AddParam( pars, "A number", &dvalue, TYPE_double_t );
return pars;
}
void PrintParameters( Parameters *pars ){
Param *this, *next = NULL;
this = pars->head;
if ( this ) { next = this->next; }
while ( this ){
if ( this->type == TYPE_double_t ) { fprintf( stdout, "%s is %lf\n", this->name, *(double*)this->value ); }
else if ( this->type == TYPE_string_t ) { fprintf( stdout, "%s is %s\n", this->name, *(char**)this->value ); }
this = next;
if ( this ) { next = this->next; }
}
}
int main (){
Parameters *pars = CreateParameters( );
PrintParameters( pars );
RemoveParameters( pars );
return 0;
}
我可以用不同的方式将字符串参数添加到链表中,还是以不同的方式释放它们,这样可以避免内存泄漏?释放svalue
函数中的CreateParameters()
字符串会导致它从链接列表中删除,尽管变量为memcpy
。
很抱歉,如果这是重复的,答案可以在其他地方找到。
修复泄漏的代码的编辑:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// compile with: gcc -g test_list.c -o test_list
// to check memory leaks run:
// >> valgrind --leak-check=full -v ./test_list
typedef enum tagParamType {
TYPE_double_t = 0,
TYPE_string_t
} ParamType;
size_t TypeSize[2] = {
sizeof(double),
sizeof(const char*)
};
typedef struct tagParam {
char name[1024]; /* Parameter name */
void *value; /* Parameter value */
ParamType type; /* type of parameter */
struct tagParam *next;
} Param;
typedef struct tagParameters {
Param *head;
} Parameters;
void AddParam( Parameters *pars, const char *name, const void *value, ParamType type );
void RemoveParameters( Parameters *pars );
Parameters *CreateParameters( );
void PrintParameters( Parameters *pars );
void AddParam( Parameters *pars, const char *name, const void *value, ParamType type ){
Param *par = NULL;
par = malloc(sizeof(Param));
memset(par, 0, sizeof(Param)); // set everything to 0
if ( type == TYPE_string_t ){
par->value = (void *)strndup((const char*)value, TypeSize[type]);
}
else{
par->value = (void *)malloc( TypeSize[type] );
memcpy( par->value, value, TypeSize[type] );
}
strncpy( par->name, name, 1024 );
par->type = type;
par->next = pars->head;
pars->head = par;
}
void RemoveParameters( Parameters *pars ){
Param *this, *next = NULL;
for ( this = pars->head, next = this->next ; this; ){
free( this->value );
free( this );
this = next;
if ( this ){ next = this->next; }
}
pars->head = NULL;
}
Parameters *CreateParameters( ){
Parameters *pars = calloc(sizeof(*pars), 1);
/* add a string */
const char *svalue = strdup("Matthew");
AddParam( pars, "First name", (const void*)svalue, TYPE_string_t );
/* add a double */
double dvalue = 0.1;
AddParam( pars, "A number", &dvalue, TYPE_double_t );
free((char*)svalue);
return pars;
}
void PrintParameters( Parameters *pars ){
Param *this, *next = NULL;
for ( this = pars->head, next = this->next ; this; ){
if ( this->type == TYPE_double_t ) { fprintf( stdout, "%s is %lf\n", this->name, *(double*)this->value ); }
else if ( this->type == TYPE_string_t ) { fprintf( stdout, "%s is %s\n", this->name, (char*)this->value ); }
this = next;
if ( this ){ next = this->next; }
}
}
int main (){
Parameters *pars = CreateParameters( );
PrintParameters( pars );
RemoveParameters( pars );
free( pars );
return 0;
}