在我开始之前
我搜索了"类似标题的问题",虽然我发现了一些非常有用的信息,但我似乎无法让它为我工作.
这与家庭作业有关.虽然,不是实际的项目本身.我已经完成了我只是将它从java移植到C所以我可以测试我的教授单元测试框架.
好的,动态分配的数组.我知道如何构建它们,但不知道如何构建它们.
例如我有以下界面..
void insertVertex( vertex p1, vertex out[], int *size);
Run Code Online (Sandbox Code Playgroud)
此方法采用顶点并将其存储到out数组中.存储顶点后,我增加了未来调用的长度计数.
p1 - 是我要添加的顶点.
out [] - 是我需要存储的数组(总是满的)
length - 当前长度
顶点定义为..
typedef struct Vertex{
int x;
int y;
} Vertex;
Run Code Online (Sandbox Code Playgroud)
这就是我在java中使用的..
Vertex tempOut = new Vertex[size +1];
//Code to deep copy each object over
tempOut[size] = p1;
out = tempOut;
Run Code Online (Sandbox Code Playgroud)
这是我认为我可以用于...
out = realloc(out, (*size + 1) * sizeof(Vertex));
out[(*size)] = p1;
Run Code Online (Sandbox Code Playgroud)
但是,我继续收到一条错误消息,指出该对象未动态分配.
我发现了一个可以解决这个问题的解决方案.我没有使用Vertex*而是转向Vertex**并存储指针与顶点.但是,在切换完所有内容之后,我发现我已经看过单元测试将为我提供一个Vertex out []的事实,即必须存储所有内容.
我也试过以下没有运气.
Vertex* temp = (Vertex *)malloc((*size + 1) * sizeof(Vertex));
for(int i = 0; i < (*size); i++)
{
temp[i] = out[i];
}
out = temp;
Run Code Online (Sandbox Code Playgroud)
但是,无论我做什么,当我测试这两个后返回的数组都没有改变.
任何帮助表示赞赏.
更新 - 请求的信息
out - 被定义为Vertex数组(Vertex out [])
它最初是用我的多边形中的顶点数构建的.例如.
out =(Vertex*)malloc(vertexInPolygon*sizeof(Vertex))
其中vertexInPolygon是多边形中顶点数的整数.
长度是应该是大小的拼写错误.
Size是一个整数指针
int *size = 0;
Run Code Online (Sandbox Code Playgroud)
每次顶点在剪切平面中时,我们将它添加到顶点数组并将大小增加一.
更新
谢谢大家的帮助.为了更好地解释自己,我想出了一个简短的程序来展示我正在尝试做的事情.
#include <stdio.h>
#include <stdlib.h>
typedef struct Vertex {
int x, y;
} Vertex;
void addPointerToArray(Vertex v1, Vertex out[], int *size);
void addPointerToArray(Vertex v1, Vertex out[], int *size)
{
int newSize = *size;
newSize++;
out = realloc(out, newSize * sizeof(Vertex));
out[(*size)] = v1;
// Update Size
*size = newSize;
}
int main (int argc, const char * argv[])
{
// This would normally be provided by the polygon
int *size = malloc(sizeof(int)); *size = 3;
// Build and add initial vertex
Vertex *out = (Vertex *)malloc((*size) * sizeof(Vertex));
Vertex v1; v1.x = 1; v1.y =1;
Vertex v2; v2.x = 2; v2.y =2;
Vertex v3; v3.x = 3; v3.y =3;
out[0] = v1;
out[1] = v2;
out[2] = v3;
// Add vertex
// This should add the vertex to the last position of out
// Should also increase the size by 1;
Vertex vertexToAdd; vertexToAdd.x = 9; vertexToAdd.y = 9;
addPointerToArray(vertexToAdd, out, size);
for(int i =0; i < (*size); i++)
{
printf("Vertx: (%i, %i) Location: %i\n", out[i].x, out[i].y, i);
}
}
Run Code Online (Sandbox Code Playgroud)
一个长期的问题是您没有从addPointerToArray()函数返回更新的数组指针:
void addPointerToArray(Vertex v1, Vertex out[], int *size)
{
int newSize = *size;
newSize++;
out = realloc(out, newSize * sizeof(Vertex));
out[(*size)] = v1;
// Update Size
*size = newSize;
}
Run Code Online (Sandbox Code Playgroud)
重新分配空间时,它可以移动到新位置,因此from的返回值realloc()不必与输入指针相同。当您添加到数组时没有其他内存分配正在进行时,这可能会起作用,因为这realloc()将在有空间的情况下扩展现有分配,但是一旦您在读取顶点时开始分配其他数据,它将彻底失败。有两种方法可以解决此问题:
Vertex *addPointerToArray(Vertex v1, Vertex out[], int *size)
{
int newSize = *size;
newSize++;
out = realloc(out, newSize * sizeof(Vertex));
out[(*size)] = v1;
// Update Size
*size = newSize;
return out;
}
Run Code Online (Sandbox Code Playgroud)
和调用:
out = addPointerToArray(vertexToAdd, out, size);
Run Code Online (Sandbox Code Playgroud)
另外,您可以传递一个指向数组的指针:
void addPointerToArray(Vertex v1, Vertex **out, int *size)
{
int newSize = *size;
newSize++;
*out = realloc(*out, newSize * sizeof(Vertex));
(*out)[(*size)] = v1;
// Update Size
*size = newSize;
}
Run Code Online (Sandbox Code Playgroud)
和调用:
out = addPointerToArray(vertexToAdd, &out, size);
Run Code Online (Sandbox Code Playgroud)
这些重写都不能解决微妙的内存泄漏。问题是,如果您realloc()用返回值覆盖传入的值,但realloc()失败了,则会丢失指向(仍然)分配的数组的指针-内存泄漏。使用时realloc(),请使用如下成语:
Vertex *new_space = realloc(out, newSize * sizeof(Vertex));
if (new_space != 0)
out = new_space;
else
...deal with error...but out has not been destroyed!...
Run Code Online (Sandbox Code Playgroud)
请注意,realloc()一次添加一个新项目会导致(可能导致)二次行为。您最好分配一大块内存-例如,将分配的空间加倍:
int newSize = *size * 2;
Run Code Online (Sandbox Code Playgroud)
如果您担心过度分配,请在读取循环结束时使用realloc(),将分配的空间缩小到数组的确切大小。但是,要做更多的簿记工作。您需要输入以下值:分配给数组的顶点数,以及实际使用的顶点数。
最后,至少现在至少要注意,您确实应该保持一致,并使用addPointerToArray()前三个条目添加到数组中。我可能会使用类似于以下(未经测试)的代码:
struct VertexList
{
size_t num_alloc;
size_t num_inuse;
Vertex *list;
};
void initVertexList(VertexList *array)
{
// C99: *array = (VertexList){ 0, 0, 0 };
// Verbose C99: *array = (VertexList){ .num_inuse = 0, .num_alloc = 0, .list = 0 };
array->num_inuse = 0;
array->num_alloc = 0;
array->list = 0;
}
void addPointerToArray(Vertex v1, VertexList *array)
{
if (array->num_inuse >= array->num_alloc)
{
assert(array->num_inuse == array->num_alloc);
size_t new_size = (array->num_alloc + 2) * 2;
Vertex *new_list = realloc(array->list, new_size * sizeof(Vertex));
if (new_list == 0)
...deal with out of memory condition...
array->num_alloc = new_size;
array->list = new_list;
}
array->list[array->num_inuse++] = v1;
}
Run Code Online (Sandbox Code Playgroud)
如果传入的指针为null realloc(),则使用会违反直觉的属性malloc()。您可以改为进行检查,array->list == 0然后使用malloc()then和realloc()其他方式。
您可能会注意到,这种结构也简化了调用代码。您不再需要处理int *size;主程序中的单独文件(及其内存分配);尺寸有效地捆绑为VertexList结构num_inuse。现在,主程序可能会启动:
int main(void)
{
VertexList array;
initVertexList(&array);
addPointerToArray((Vertex){ 1, 1 }, &array); // C99 compound literal
addPointerToArray((Vertex){ 2, 2 }, &array);
addPointerToArray((Vertex){ 3, 3 }, &array);
addPointerToArray((Vertex){ 9, 9 }, &array);
for (int i = 0; i < array->num_inuse; i++)
printf("Vertex %d: (%d, %d)\n", i, array->list[i].x, array->list[i].y, i);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
(碰巧的是,此序列仅会调用一次内存分配,因为新大小(old_size + 2) * 2是在第一次为数组分配4个元素时。通过添加新点或将公式细化为或,很容易进行重新分配(old_size + 1) * 2。 ..
如果您打算从内存分配失败中恢复(而不是从发生这种情况时退出),那么您应该进行修改addPointerToArray()以返回一个状态(成功,但不成功)。
此外,函数名可能应该addPointToArray()或者addVertexToArray()甚至addVertexToList()。
| 归档时间: |
|
| 查看次数: |
9260 次 |
| 最近记录: |