我刚刚用我正在编写的当前程序解决了内存分配问题,但我不满意我必须做些什么来解决它。
在我的程序中,我正在构建一个结构数组,每次我想为它添加一个结构时重新分配数组的空间。这是我的struct的通用版本以及将向数组添加结构的函数:
typedef struct Example {
const char* name;
int (*func)(int, int);
int bool_switch;
}
int add_struct_to_array( Example **example_array, int *ex_array_size, int name, int (*func)(int, int), int bool_switch)
{
// first, make a new struct
Example *new_example = (Example *) calloc( 1, sizeof( Example ) );
if( new_example != NULL ) {
new_example->name = name;
new_example->func = func;
new_example->bool_switch = bool_switch;
( *ex_array_size )++;
} else {
printf( "Errror allocating %s\n", name );
exit( -1 );
}
// now, realloc the array of structs and add the new member to it
Example **temp_example_array = ( Example** )realloc( example_array, ( *ex_array_size ) * sizeof( Example* ) );
if( temp_example_array != NULL ) {
example_array = temp_example_array;
example_array[ ( *ex_array_size ) - 1 ] = new_example;
} else {
printf( "Reallocation failed\n" )
exit( -1 );
}
return 0;
}
这里是我调用函数的地方(请注意我最初是如何分配结构数组的,因为这就是问题所在的位置)
#include "example_struct.h"
int main( int argc, char **argv )
{
int ex_array_size = 0;
Example **example_array = ( Example** )calloc( 0, sizeof( Example* ) );
add_struct_to_array( example_array, &ex_array_size, "name", &function, 1 );
...
...
add_struct_to_array( example_array, &ex_array_size, "other_name", &other_func, 0 );
/* Do stuff here */
example_array_free( example_array );
return 0;
}
在我的无知中,我显然认为分配大小为0的数组是可以的,因为它最初是空的,我可以在之后添加结构。显然,这不起作用,我会得到关于error for object 0x100100080: pointer being reallocated was not allocated
的运行时错误。 example_array
位于地址0x100100080
,我将分配的第一个结构位于地址0x100100090
,经过一些重新分配后,example_array
将耗尽空间。< / p>
所以,最后,我的问题。我通过为example_array
分配比我需要的更多空间来解决这个问题,但这似乎非常不优雅。有更好的方法吗?
**编辑**
好的,从大多数响应的外观来看,我不应该使用指针指针。所以,我尝试的方式略有不同,混合了pmg
和crypto
的回复。这是我现在的代码:
/* example_struct.h */
int add_struct_to_array( Example *example_array, int *ex_array_size, int name, int (*func)(int, int), int bool_switch)
{
Example temp_example_array = realloc( example_array, ( ( *ex_array_size ) + 1 ) * sizeof( Example ) );
if( temp_example_array != NULL ) {
example_array = temp_example_array;
Example new_example;
new_example.name = name;
new_example.func = func;
new_example.bool_switch = bool_switch;
example_array[ ( *ex_array_size ) ] = new_example;
++( *ex_array_size );
} else {
fprintf( stderr, "Error reallocating for %s", name );
exit( -1 );
}
return 0;
}
/* main.c */
...
...
#include "example_struct.h"
int main( int argc, char **argv )
{
int ex_array_size = 0;
Example *example_array = NULL;
add_struct_to_array( example_array, &ex_array_size, "name", &func, 1 );
add_struct_to_array( ... );
...
add_struct_to_array( example_array, &ex_array_size, "other name", &other_func, 0 );
example_free( example_array );
}
一切都编译好realloc
没关系,但我无法访问数组中的结构。
/* main.c */
...
...
#include "example_struct.h"
int main( int argc, char **argv )
{
int ex_array_size = 0;
Example *example_array = NULL;
add_struct_to_array( example_array, &ex_array_size, "name", &func, 1 );
add_struct_to_array( ... );
...
add_struct_to_array( example_array, &ex_array_size, "other name", &other_func, 0 );
printf( "%s\n", example_array[0].name ) /* Segfault */
example_free( example_array );
}
再次感谢您的帮助。
答案 0 :(得分:4)
realloc
将NULL作为指针值非常精细......在这种情况下执行malloc
*p = NULL;
new = realloc(p, 42); /* same as new = malloc(42); */
if (!new) { /* error */ }
p = new;
所以,忘记calloc
(无论如何,你将在之后覆盖零),将你的指针初始化为NULL并realloc
随意。
int main(void) {
Example *example_array = NULL;
add_struct_to_array(&example_array, &ex_array_size, "name", function, 1);
/* ... */
free(example_array);
}
答案 1 :(得分:1)
尝试以下更改。您不需要分配任何额外的空间。
修改:添加 pmg &amp ;; Bart van Ingen Schenau
int add_struct_to_array( Example ***example_array, int *ex_array_size, int name, int (*func)(int, int), int bool_switch)
{
Example **temp_example_array = realloc(*example_array,((*ex_array_size) + 1) * sizeof(Example *) );
Example *new_example = calloc(1, sizeof( Example ) );
if( temp_example_array != NULL && new_example != NULL ) {
*example_array = temp_example_array;
*example_array[ *ex_array_size ] = new_example;
new_example->name = name;
new_example->func = func;
new_example->bool_switch = bool_switch;
( *ex_array_size )++;
} else {
printf( "Error allocating %s\n", name );
exit( -1 );
}
return 0;
}
#include "example_struct.h"
int main( int argc, char **argv )
{
int ex_array_size = 0;
Example **example_array = calloc( 0, sizeof( Example* ) );
add_struct_to_array( &example_array, &ex_array_size, "name", &function, 1 );
...
add_struct_to_array( &example_array, &ex_array_size, "other_name", &other_func, 0 );
...
example_array_free( example_array );
return 0;
}
为了避免破坏任何其他代码,我使用了指针指针example_array。虽然,更好的解决方案是简单地使用指向结构的指针,&amp;保持realloc()空间。
答案 2 :(得分:0)
似乎std :: vector完全符合您的需求。它与数组一样快,并且知道如何管理内存。一个简单的例子如下。
向量使用连续内存,就像数组一样。如果您知道需要多少个Example对象,您可以告诉向量在构造函数中需要多大。如果您不知道有多少将会增长以满足您的需求。如果性能很重要,那么尝试在构造函数中分配内存总量,因为当向量重新分配时,它将创建一个新的连续内存块,然后将每个对象复制到新的内存区域(示例构造函数和析构函数将在此时执行)发生)。
查看向量here的不同构造函数,capacity()和reserve()。
#include <vector>
int function_1(int a, int b) {
return 100;
}
int function_2(int a, int b) {
return 200;
}
typedef struct {
int name;
int (*func)(int, int);
int bool_switch;
} example_t;
typedef std::vector<example_t> example_container_t;
int main() {
example_container_t container;
example_t example_1;
example_1.name = 1;
example_1.func = &function_1;
example_1.bool_switch = true;
container.push_back(example_1);
example_t example_2;
example_2.name = 1;
example_2.func = &function_1;
example_2.bool_switch = true;
container.push_back(example_2);
return 0;
}
答案 3 :(得分:0)
这是一个最低工作版本(有许多标识符的C ++关键字 - 我有点道歉,但是当我开始并且我无法停止或中途返回时它看起来很有趣)也运行在ideone上({{3 }})
#include <stdio.h>
#include <stdlib.h>
struct protected {
int this;
int (*catch)(int, int);
int friend;
};
int catch(int mutable, int virtual) {
return mutable + virtual;
}
struct protected *add_one(struct protected **private,
int *explicit, int using,
int (*catch)(int, int), int friend) {
struct protected *new;
new = realloc(*private, (*explicit + 1) * sizeof *new);
if (new) {
*private = new;
(*private)[*explicit].this = using;
(*private)[*explicit].catch = catch;
(*private)[*explicit].friend = friend;
(*explicit)++;
}
return new;
}
/* create an array of structs using dynamic memory */
/* keep adding elements to it, and growing it as needed */
int main(void) {
int using;
/* explicit contains the number of elements in the try array */
int explicit = 0;
struct protected *try = NULL;
/* create and grow */
for (using = 0; using < 7; using++) {
if (add_one(&try, &explicit, using + 1, catch, 0) == NULL) {
fprintf(stderr, "failure at loop %d\n", using);
exit(EXIT_FAILURE);
}
}
/* verify */
for (using = 0; using < explicit; using++) {
printf("%d: %d\n", using, try[using].this);
}
free(try);
return 0;
}