我正在研究一个相当旧的软件包(NWChem)的模块,并且不确定从一对相当常用的函数调用中创建函数的最佳方法。主包内部是一组用于操作运行时数据库的函数。我经常使用的对是rtdb_get_info
和rtdb_get
来提取有关数据库中一个值的内容的信息并获取实际值。这些函数的标题是:
extern int rtdb_get_info(const int, const char *, int *, int *, char [26]);
extern int rtdb_get(const int, const char *, const int, const int, void *);
它们的调用方式是执行以下操作(忽略返回值):
int nelem, ma_type;
char date[26];
rtdb_get_info(rtdb, "nameofrtdbvalue", &ma_type, &nelem, date)
rtdb_get(rtdb, "nameofrtdbvalue", ma_type, array)
其中rtdb是在其他地方设置的整数,用于指定要访问的数据库,array是要存储“nameofrtdbvalue”中存储的值的数组。在某些情况下,您可能会在进行实际array = malloc(nelem * sizeof *array)
来电之前rtdb_get
。
目前,我使用以下函数来调用此对:
void rtdb_pull(int rtdb, const char *name, void *array) {
int ma_type;
int nelem;
char date[26];
if (rtdb_get_info(rtdb, name, &ma_type, &nelem, date)) {
if (rtdb_get(rtdb, name, ma_type, nelem, array))
printf("Retrieved %s from rtdb.\n", name);
else
printf("%s is in rtdb, but not retrievable.\n", name);
}
else
printf("Couldn't get info on %s from rtdb.\n", name);
}
以下是我将分配内容并致电rtdb_pull
的示例方式。在这种情况下,我将从数据库中提取一个 3 * npoints 双精度数组,然后将它们传递给其他一些使用数组 coords 执行某些操作的函数。通常这会发生在我需要重新分配内存的循环中。
double *coords=malloc(sizeof *coords);
int npoints, rtdb;
int i, nloops;
char buf[32];
get_rtdb(&rtdb); //Just something that gets the integer for the runtime database
for (i=0;i<nloops;i++) {
get_npoints(&npoints);
coords=realloc(coords,npoints * sizeof *coords);
rtdb_pull(rtdb,"geometryname",coords);
use_coords(coords);
}
free(coords);
rtdb_pull
是我在学习c时写的第一个函数之一,我注意到我称之为越多,我就越有可能得到分段错误,所以我想重写它,但我不确定最好的方法。似乎调用它会导致内存泄漏,但我不确定原因。也许这与我将一个指针分配给一个双精度数组的内存指向void *的事实有关?如果是这样,我不确定如何解决这个问题(并且不断调用这对函数真的很烦人)。
有任何想法或建议吗?
答案 0 :(得分:1)
使用void *没有错误,当你需要时,它们可以像通用类型那样工作,而且它似乎是你想要的,对吗?
int myfunc(void* data, int op)
{
double *mycoords;
if(op == 1) // a way to control the real type
mycoords = (double*) data;
//...
return 0;
}
在函数内部,您可以转换或将(void *)转换为您需要的类型。
另一种方法是编写一个带有变量参数列表的函数,这是stdarg手册页中的一个例子:
#include <stdio.h>
#include <stdarg.h>
void
foo(char *fmt, ...)
{
va_list ap;
int d;
char c, *s;
va_start(ap, fmt);
while (*fmt)
switch (*fmt++) {
case 's': /* string */
s = va_arg(ap, char *);
printf("string %s\n", s);
break;
case 'd': /* int */
d = va_arg(ap, int);
printf("int %d\n", d);
break;
case 'c': /* char */
/* need a cast here since va_arg only
takes fully promoted types */
c = (char) va_arg(ap, int);
printf("char %c\n", c);
break;
}
va_end(ap);
}
答案 1 :(得分:1)
我没有发现您的rtdb_pull
方法有任何问题,与void *
这样的工作完全没问题。所以也许问题出在其他地方:
rtdb_get_info
和rtdb_get
坚如磐石且经过充分测试的?free( coords );
语句,这是正常的吗?答案 2 :(得分:1)
您对rtb_get_info的调用会更新nelem中的值,该值来自上下文,我认为是要存储到数组中的元素数量。但是,您根据npoints的值来确定数组的大小,您知道这些值是否相同?我们无法看到如何设置npoints。
此外,get_npoints()函数看起来不适合C代码。 npoints被声明为一个int,我不知道如何通过调用get_npoints()来更新它,在C ++中我认为它是一个引用,但这是C。
答案 3 :(得分:0)
这句话让我很烦恼:
double *coords=malloc(sizeof *coords);
coords是指向一个或多个双精度的指针很好,但你必须在某处为它分配真实的内存。 sizeof *coords
意味着什么?你真的想让malloc()的参数成为你对这个数组所需的总字节数,我不认为你是这么做的。您还需要将返回的指针强制转换为double *。您使用的是非常旧的C编译器,错误检测效果不佳吗?
无论如何,开始清理你的代码,并在整个代码中添加一些注释来解释你想要做的事情。