我一直在努力解决malloc和realloc背后的思想,这已经有一段时间了,目前我在动态创建结构数组方面存在问题。我有一个struct triangle
,它本身由struct coordinates
的数组组成。我希望能够有一个triangles
数组,该数组必须足够大,但是每次我尝试增加数组的长度时,似乎什么都没有发生。 Realloc不会失败,malloc也不会失败。但是,新三角形未插入我的数组中。这是我的代码供参考。
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
struct coordinate {
int x;
int y;
};
struct triangle {
struct coordinate point[3];
};
static size_t size = 0;
static void addTriangle(struct triangle **triangles, struct triangle *t) {
struct triangle *ts = (struct triangle*) realloc(*triangles, (size+1) * sizeof(struct triangle));
if(ts == NULL) {
free(ts);
exit(EXIT_FAILURE);
}
*triangles = ts;
triangles[size] = t;
size++;
}
int main() {
struct triangle* triangles = (struct triangle *) malloc(sizeof(struct triangle));
if(triangles == NULL) {
free(triangles);
exit(EXIT_FAILURE);
}
for(int i = 0; i < 2; i++) {
struct coordinate *a = malloc(sizeof(struct coordinate));
a->x = 1 * i;
a->y = 2 * i;
struct coordinate *b = malloc(sizeof(struct coordinate));
b->x = 3 * i;
b->y = 4 * i;
struct coordinate *c = malloc(sizeof(struct coordinate));
c->x = 5 * i;
c->y = 6 * i;
struct triangle *t = malloc(sizeof(struct triangle));
t->point[0] = *a;
t->point[1] = *b;
t->point[2] = *c;
addTriangle(triangles, t);
}
}
我已经尝试了所有发现的变体,但是我宁愿不只是盲目地将&和*扔进去,直到发生某些事情为止。
答案 0 :(得分:3)
照原样,您的程序在将未初始化的*triangles
传递给realloc
:https://taas.trust-in-soft.com/tsnippet/t/9ff94de4时会调用未定义的行为。您可能打算在&triangles
中调用main
时通过。{p>
将main
中的呼叫更改为addTriangle(&triangles, t);
,下一个问题是addTriangle
:https://taas.trust-in-soft.com/tsnippet/t/658228a1内部的越界访问。同样,这可能是因为您具有错误的间接级别,并且意味着诸如(*triangles)[size]
之类的东西。
而不是triangles[size]
。
如果将行triangles[size] = t;
更改为(*triangles)[size] = *t;
,则没有未定义的行为。由于已对其进行了修改,因此应检查该程序是否仍能满足您的要求:https://taas.trust-in-soft.com/tsnippet/t/8915bd2d
最终版本:
#include <string.h>
#include <stdlib.h>
struct coordinate {
int x;
int y;
};
struct triangle {
struct coordinate point[3];
};
static size_t size = 0;
static void addTriangle(struct triangle **triangles, struct triangle *t) {
struct triangle *ts = (struct triangle*) realloc(*triangles, (size+1) * sizeof(struct triangle));
if(ts == NULL) {
free(ts);
exit(EXIT_FAILURE);
}
*triangles = ts;
(*triangles)[size] = *t; // a struct assignment
size++;
}
int main() {
struct triangle* triangles = (struct triangle *) malloc(sizeof(struct triangle));
if(triangles == NULL) {
free(triangles);
exit(EXIT_FAILURE);
}
for(int i = 0; i < 2; i++) {
struct coordinate *a = malloc(sizeof(struct coordinate));
a->x = 1 * i;
a->y = 2 * i;
struct coordinate *b = malloc(sizeof(struct coordinate));
b->x = 3 * i;
b->y = 4 * i;
struct coordinate *c = malloc(sizeof(struct coordinate));
c->x = 5 * i;
c->y = 6 * i;
struct triangle *t = malloc(sizeof(struct triangle));
t->point[0] = *a;
t->point[1] = *b;
t->point[2] = *c;
addTriangle(&triangles, t); /* pass the address of triangles
so that addTriangle can modify this variable's contents */
}
}
只要您使用C编程,请do not cast the result of malloc
。只需编写struct triangle* triangles = malloc(...
。
正如@aschepler在评论中指出的那样,该程序仍会泄漏从main
分配的内存块。这些可以在每次迭代结束时释放,而无需添加任何未定义的行为:https://taas.trust-in-soft.com/tsnippet/t/a0705262。这样做,您可能会意识到t->point[0] = *a;
,...实际上是结构分配,并且没有必要首先分配单独的struct coordinate
:您只需填写每个{{1} } struct coordinate
的成员。另外,也不必在struct triangle
中分配struct triangle
:您可以为此使用局部变量,因为无论如何,结构的内容将由函数{{1}复制}到main
的局部变量addTriangle
指向的数组。
如果main
是triangles
中的空指针,则无需调用free(triangles)
:
triangles
允许将空指针传递到main
,这可以达到您的期望(不执行任何操作),但是由于您知道struct triangle* triangles = (struct triangle *) malloc(...
if(triangles == NULL) {
free(triangles);
exit(EXIT_FAILURE);
}
在{ {1}}分支,只需调用free
。
处理triangles
on the other hand is a subtle subject的失败。您的程序做错了,但没关系,因为它会立即调用NULL
。
在静态文件范围变量then
中存储有关exit
的局部变量realloc
指向的已分配数组的信息不一致。两者是如此紧密地联系在一起,因此它们应该在同一范围内。由于您需要exit
才能更改main
,因此不能简单地将triangles
设置为size
的局部变量,而可以将局部变量{{1 addTriangle
中的}}文件范围,位于size
旁边。如果您毕竟希望将size
设为main
的局部变量,则需要将其地址传递给函数triangles
,以便后者可以更新前者。
答案 1 :(得分:0)
您可以将Invalid value for field 'resource.disks[0].source': ''. Source url of disk is missing.
循环的整个部分替换为
const createVM = () => {
const Compute = require('@google-cloud/compute');
const compute = new Compute();
const zone = compute.zone('us-central1-f');
let disk;
const diskName = 'debian-http-disk';
const vmName = 'debian-http'
let vm;
disk = zone.disk(diskName);
zone
.createVM(vmName, {
disks: [disk],
http: true,
machineType: 'f1-micro'
})
.then((data) => {
vm = data[0];
const operation = data[1];
return operation.promise();
})
.then(() => {
console.log('vm created successfully');
})
.catch((e) => {
console.error(e);
});
};
请注意参数前的for
,因为您想同时传递两者的地址。
我已经注意到struct triangle t = {{{i, 2*i},{3*i,4*i},{5*i,6*i}}};
addTriangle(&triangles, &t);
应该是&
triangles[size] = t;
答案 2 :(得分:0)
将函数调用更改为
addTriangle(&triangles, t);