c - 如何为函数内部的结构分配动态内存插槽,可以从程序中的任何位置访问


int insert(struct node *temp, char *input_string, int str_len) {
char ch = *input_string;
int copied=str_len;
int i;
temp =(struct node *) temp->child_nodes[ch];
if (temp->data[0] == "NULL") { //when the node is empty and has no data in its data[]
for (i = 0; i < str_len; i++) {
temp->data[i] = *input_string;//copy the character into the array
input_string++;//increment the pointer to get next character to be inserted
}//for closed
return 1; //function job completed
}//if closed
else {
i = 0;
while (str_len - copied) {
if (temp->data[i] == ch) {//till the characters are same to be inserted.
copied++;
i++;
input_string++;
ch = *input_string;
continue;
}
else //when the data to be inserted is not same.
{
//initialise a node1 and node2 memory code here.
temp->no_of_child_nodes += 2;
temp->child_nodes[temp->data[i]] = (struct node*) malloc(sizeof(struct node));
temp->child_nodes[ch] = malloc(sizeof(struct node));
while (temp->data[i] != "NULL") {//check for the parent node data to reach NULL
node1->data[i] = temp->data[i];//copy data
i++;//increment I       
}
while (str_len - copied) {
node2->data[i] = ch;
input_string++;
ch++;
}
}
}
}
}

在函数插入中,我面临需要在函数中添加两个结构节点的情况。由于分配的内存将在退出函数时释放,因此我该如何解决此问题?

为了能够在任何地方访问动态分配的结构,您需要访问它的位置才能在任何地方引用它,为此我们使用指针。我给大家举个例子。

假设您有一个Point数据类型来表示三维空间中的点。

typedef struct point_t {
double x;
double y;
double z;
} *Point;

现在你可以创建一个"builder"函数 - 与C++中的构造函数不同,尽管不完全是 - 您可以在其中设置其初始值并返回其指针。这就是动态分配结构并保留指向它的指针的方式,以便您可以在程序的其他部分中继续使用它。

Point createPoint(double a, double b, double c) {
Point newPoint = malloc(sizeof(struct point_t));
if (newPoint == NULL) { /* Handle failure here... */ }
SetPoint(&newPoint,a,b,c);
return newPoint;
}

然后你会像这样定义SetPoint

void SetPoint(Point* p, double a, double b, double c) {
if (p == NULL) { return; }
*p->x = a;
*p->y = b;
*p->z = c;
}

要实际使用该结构,您必须做两件事。首先,你必须构造结构,然后你必须把它传递给需要它的另一个函数。你已经在上面的SetPoint函数中看到了这一点。

请注意,Point* p声明了一个指向类型struct point_t的结构的双指针。我们需要一层间接寻址来处理指针本身,然后需要一层额外的间接寻址,以便我们可以通过引用传递指针并在函数中修改其内容。如果我们传入常规Point句柄,则按值传递机制将丢弃函数的效果。

因此,对于这种假设的数据结构,您的main函数可能会像这样使用它:

int main()
{
Point origin = createPoint(0,0,0);
PrintPoint(origin);
Point p1 = createPoint(1,-1,5);
PrintPoint(p1);
printf("Distance between p1 and the origin: %lfn", DistanceBetween(p1,origin));
return EXIT_SUCCESS;
}

您可以像这样定义Print Point

void PrintPoint(Point p) {
if (p == NULL) { return; }
printf("(%lf,%lf,%lf)n", p->x, p->y, p->z);
}

同样,您可以像这样定义DistanceBetween函数:(请记住,三维欧几里得空间中任何两点之间的距离基本上是勾股定理,但有一个额外的维度。

double DistanceBetween(Point a, Point b) {
return sqrt(pow((b->x - a->x),2) + pow((b->y - a->y),2) + pow((b->z - a->z),2));
}

对于一些一般指针,请记住对NULL指针保持警惕。它们不仅会导致分段错误或给您带来垃圾结果 - 有时这甚至更糟 imo - 而且还可能导致代码漏洞,例如几年前zlib中的"双重释放"漏洞。最近还有另一个,但我没有阅读漏洞利用摘要。

如果你想用双免费来安全,你可以使用里斯教授在"理解和使用C指针"中写的方法。如果我们从上面将其应用于假设的Point结构,它看起来像这样:

void SafeFree(Point* pointHandle) {
if (*pointHandle == NULL) { return; }
free(*pointHandle);
*pointHandle = NULL;
}

请注意,我们正在通过引用传入要释放的指针(因此您必须像这样释放它:例如free(&origin)。这样我们就可以在释放它后将其设置为NULL。这样,如果要在同一内存位置调用 free,即使它被不同的指针引用,此NULL检查也会使您免于双重释放内存。

无论如何,这只是一个额外的预防措施,我希望这一切都有所帮助,如果您还有其他问题,请告诉我。

相关内容

最新更新