C 成员为函数指针和空指针的结构的内存分配错误
我编写了一个简单的C代码,它使用一个引擎根据用户输入运行两种不同的算法。它使用指向算法方法和对象的函数指针。某个地方有一个我无法追踪的严重内存错误,所以可能是我以错误的方式分配内存。出什么事了 下面是代码的一个最小工作示例(相关部分) main.cC 成员为函数指针和空指针的结构的内存分配错误,c,memory-management,function-pointers,void-pointers,C,Memory Management,Function Pointers,Void Pointers,我编写了一个简单的C代码,它使用一个引擎根据用户输入运行两种不同的算法。它使用指向算法方法和对象的函数指针。某个地方有一个我无法追踪的严重内存错误,所以可能是我以错误的方式分配内存。出什么事了 下面是代码的一个最小工作示例(相关部分) main.c #include "engine.h" int main() { char *id = "one"; Engine_t eng; Engine_init(&eng); Engine_select_algorithm(en
#include "engine.h"
int main()
{
char *id = "one";
Engine_t eng;
Engine_init(&eng);
Engine_select_algorithm(eng, id);
Engine_run(eng);
}
#include "engine.h"
#include "algorithm_one.h"
#include "algorithm_two.h"
typedef struct _Engine
{
void *p_algorithm;
void (*init)(Engine_t);
void (*run)(Engine_t);
} Engine;
void Engine_init(Engine_t *eng)
{
*eng = malloc(sizeof(Engine));
(*eng)->p_algorithm = NULL;
}
void Engine_select_algorithm(Engine_t eng, char *id)
{
if ( strcmp(id, "one") == 0 )
{
eng->init = Algorithm_one_init;
eng->run = Algorithm_one_run;
}
else if ( strcmp(id, "two") == 0 )
{
eng->init = Algorithm_two_init;
eng->run = Algorithm_two_run;
}
else
{
printf("Unknown engine %s.\n", id); exit(0);
}
eng->init(eng);
}
void Engine_run(Engine_t eng)
{
eng->run(eng);
}
void Engine_set_algorithm(Engine_t eng, void *p)
{
eng->p_algorithm = p;
}
void Engine_get_algorithm(Engine_t eng, void *p)
{
p = eng->p_algorithm;
}
#include "engine.h"
#include "algorithm_one.h"
typedef struct _A_one
{
float value;
} A_one;
void Algorithm_one_init(Engine_t eng)
{
A_one_t aone;
aone = malloc(sizeof(A_one));
aone->value = 13.0;
//int var = 10;
Engine_set_algorithm(eng, &aone);
}
void Algorithm_one_run(Engine_t eng)
{
A_one_t aone;
Engine_get_algorithm(eng, &aone);
printf("I am running algorithm one with value %f.\n", aone->value);
// The code for algorithm one goes here.
}
发动机.h
typedef struct _Engine *Engine_t;
typedef struct _A_one *A_one_t;
引擎.c
#include "engine.h"
int main()
{
char *id = "one";
Engine_t eng;
Engine_init(&eng);
Engine_select_algorithm(eng, id);
Engine_run(eng);
}
#include "engine.h"
#include "algorithm_one.h"
#include "algorithm_two.h"
typedef struct _Engine
{
void *p_algorithm;
void (*init)(Engine_t);
void (*run)(Engine_t);
} Engine;
void Engine_init(Engine_t *eng)
{
*eng = malloc(sizeof(Engine));
(*eng)->p_algorithm = NULL;
}
void Engine_select_algorithm(Engine_t eng, char *id)
{
if ( strcmp(id, "one") == 0 )
{
eng->init = Algorithm_one_init;
eng->run = Algorithm_one_run;
}
else if ( strcmp(id, "two") == 0 )
{
eng->init = Algorithm_two_init;
eng->run = Algorithm_two_run;
}
else
{
printf("Unknown engine %s.\n", id); exit(0);
}
eng->init(eng);
}
void Engine_run(Engine_t eng)
{
eng->run(eng);
}
void Engine_set_algorithm(Engine_t eng, void *p)
{
eng->p_algorithm = p;
}
void Engine_get_algorithm(Engine_t eng, void *p)
{
p = eng->p_algorithm;
}
#include "engine.h"
#include "algorithm_one.h"
typedef struct _A_one
{
float value;
} A_one;
void Algorithm_one_init(Engine_t eng)
{
A_one_t aone;
aone = malloc(sizeof(A_one));
aone->value = 13.0;
//int var = 10;
Engine_set_algorithm(eng, &aone);
}
void Algorithm_one_run(Engine_t eng)
{
A_one_t aone;
Engine_get_algorithm(eng, &aone);
printf("I am running algorithm one with value %f.\n", aone->value);
// The code for algorithm one goes here.
}
算法_one.h
typedef struct _Engine *Engine_t;
typedef struct _A_one *A_one_t;
算法_one.c
#include "engine.h"
int main()
{
char *id = "one";
Engine_t eng;
Engine_init(&eng);
Engine_select_algorithm(eng, id);
Engine_run(eng);
}
#include "engine.h"
#include "algorithm_one.h"
#include "algorithm_two.h"
typedef struct _Engine
{
void *p_algorithm;
void (*init)(Engine_t);
void (*run)(Engine_t);
} Engine;
void Engine_init(Engine_t *eng)
{
*eng = malloc(sizeof(Engine));
(*eng)->p_algorithm = NULL;
}
void Engine_select_algorithm(Engine_t eng, char *id)
{
if ( strcmp(id, "one") == 0 )
{
eng->init = Algorithm_one_init;
eng->run = Algorithm_one_run;
}
else if ( strcmp(id, "two") == 0 )
{
eng->init = Algorithm_two_init;
eng->run = Algorithm_two_run;
}
else
{
printf("Unknown engine %s.\n", id); exit(0);
}
eng->init(eng);
}
void Engine_run(Engine_t eng)
{
eng->run(eng);
}
void Engine_set_algorithm(Engine_t eng, void *p)
{
eng->p_algorithm = p;
}
void Engine_get_algorithm(Engine_t eng, void *p)
{
p = eng->p_algorithm;
}
#include "engine.h"
#include "algorithm_one.h"
typedef struct _A_one
{
float value;
} A_one;
void Algorithm_one_init(Engine_t eng)
{
A_one_t aone;
aone = malloc(sizeof(A_one));
aone->value = 13.0;
//int var = 10;
Engine_set_algorithm(eng, &aone);
}
void Algorithm_one_run(Engine_t eng)
{
A_one_t aone;
Engine_get_algorithm(eng, &aone);
printf("I am running algorithm one with value %f.\n", aone->value);
// The code for algorithm one goes here.
}
算法_two.h和算法_two.c的代码与算法一文件相同
一定有内存错误,因为代码按照给定的方式运行,但是如果我取消注释
//int var = 10;
在algoritm\u one.c中的行代码因分段错误而崩溃。您将错误的内容传递给
引擎集\u算法
。您传递的是局部变量的地址,而不是算法的地址。你需要写:
Engine_set_algorithm(eng, aone);
而且Engine\u get\u算法
也是错误的。您将按值传递一个指针,并修改该指针。因此调用方无法看到该修改。你需要它是:
void Engine_get_algorithm(Engine_t eng, void **p)
{
*p = eng->p_algorithm;
}
我认为如果定义一个类型来表示一个算法,代码会更容易。这种类型将只是一个void*
,但它会使代码更易于阅读。而且,我会让Engine\u get\u algorithm
返回算法
algorithm Engine_get_algorithm(Engine_t eng)
{
return eng->p_algorithm;
}
void Engine_set_algorithm(Engine_t eng, algorithm alg)
{
eng->p_algorithm = alg;
}
您的
Engine\u get\u算法
函数实际上不会得到任何东西,因为p
是该函数的局部函数。您需要返回算法,或者通过指针.Argh传递p
,指针typedef
。这使得你的代码很难阅读。@Sander De Dycker谢谢,你是对的,我已经根据David Heffernan的回答进行了修改。@JensGustedt如果写起来很难,应该很难阅读。。)不,说真的,我认为在.h中的接口和.c.Hm中的实现之间有一个清晰的分离是一个好方法,这只是隐藏了一些东西。在C语言中,当您看到一个没有*
的接口时,您希望通过值传递东西。在大多数项目中,这样的界面不会通过审查。谢谢,你是对的。我应该自己发现的。你的其他建议也很好。代码现在按预期工作。为可读性定义算法类型绝对是个好主意。非常感谢您迅速而简洁的回答。