代码之家  ›  专栏  ›  技术社区  ›  A Akshat

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

  •  0
  • A Akshat  · 技术社区  · 6 年前
    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++;
                    }
                }
            }
        }
    }
    

    在函数Insert中,我面临一种需要在函数中添加两个结构节点的情况。由于分配的内存将在退出函数时释放,如何修复此问题?

    1 回复  |  直到 6 年前
        1
  •  0
  •   Jose Fernando Lopez Fernandez    6 年前

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

    假设你有 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;
    }
    

    要实际使用该结构,您必须做两件事。首先,必须构造结构,然后必须将其传递给需要它的其他函数。您已经在工作中看到了这一点 设定值 上述功能。

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

    因此,在这个假设的数据结构中 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: %lf\n", 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指针》中提到的方法如果我们将其应用于假设 指向 从上面看,它是这样的:

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

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

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