简体   繁体   English

修改结构体的指针

[英]Modify pointer of pointer of struct

I create a struct, pass the pointer of pointer into the function to then call malloc() . 我创建一个结构,将指针的指针传递到函数中,然后调用malloc() That all works fine. 一切正常。 However if I try to access the memory, the program just freezes. 但是,如果我尝试访问内存,程序将冻结。 If I call another function and change access the memory then everything works fine. 如果我调用另一个函数并更改对内存的访问,则一切正常。

void test(TFeld *Feld, TEinstellung E)
{
int i;

    for (i=0;i<E.Groesse_X*E.Groesse_Y;i++)
    {
        Feld[i].Schiff_Vorhanden = false;
        Feld[i].Schiff_Versunken = false;
        Feld[i].Ueberprueft = false;
    }   
}

void initField (TEinstellung E, TFeld **Feld)
{
    int i;

    *Feld = (TFeld*)malloc(E.Groesse_X*E.Groesse_Y*sizeof(TFeld));

    test(*Feld,E);

    /*  for (i=0;i<E.Groesse_X*E.Groesse_Y;i++)
    {
        Feld[i]->Schiff_Versunken = (bool*)false;
    //  (*Feld[i]).Schiff_Versunken = false;
        //Feld[i]->Ueberprueft = false;
    } */
}

with the definiton of TFeld: TFeld的定义:

typedef struct TFeld
{
    bool Schiff_Vorhanden = false;
    bool Ueberprueft = false;
    bool Schiff_Versunken = false;
} TFeld;

The part I commented out just crashed the program while using the test function works. 我注释掉的部分只是在使用测试功能时崩溃了程序。

Can someone please explain me that behavior. 有人可以向我解释这种行为。

Whats the problem ? 有什么问题 ?

In InitField() the parameter Feld is declared as a pointer to a pointer to TFeld. InitField() ,参数Feld被声明为指向TFeld的指针。

*Feld is hence a pointer to TFeld . *Feld因此是TFeld的指针。 It is correctly initialized to a freshly allocated memory region of the correct size. 它已正确初始化为正确大小的新分配内存区域。

You then call test() passing *Feld as argument. 然后,您调用test()并传递*Feld作为参数。 Unfortunately you call the argument Feld as well, so that the type of these variable is different and could cause some headaches. 不幸的是,您也调用了Feld参数,因此这些变量的类型不同并且可能引起一些麻烦。 But this is not the problem. 但这不是问题。 The test function should do what yo expect. 测试功能应该可以实现您的期望。

When you're back in InitField() you then try to access to the elements that you have initialized: 当您返回InitField() ,然后尝试访问已初始化的元素:

Feld[i]->Schiff_Versunken = ... //ouch !!!

This takes the pointer to pointer and access the ith pointer in that table. 这会将指针指向指针,并访问该表中的第ith个指针。 But as your pointer of pointer is just a poitner and not an array, you get back a pointer which is completely corrupt. 但是由于指针的指针只是一个Poitner而不是数组,因此您将获得一个完全损坏的指针。 You then dereference this rogue pointer with -> pretending that it points to a TFeld . 然后,使用->假装它指向TFeld来取消引用该恶意指针。 When you then assign a valu into this rogue address you have undefined behavior (could be segfault, could be freeze, could be anything). 然后,当您向该恶意地址分配一个值时,您的行为就不确定(可能是段错误,可能冻结,可能是任何事情)。

Edit: additional information on pointer dereferencing: 编辑:有关指针解引用的其他信息:

The operators * -> and [] have an order of precendence which you have to get used to. 运算符* ->[]具有必须习惯的优先顺序 Let's look at the TFeld **Feld : 让我们看一下TFeld **Feld

  • *Feld[i] is the same that *(Feld[i]) because first [] is applied and then only * . *Feld[i]*(Feld[i])相同,因为首先应用[] ,然后仅应用* By the way, going further, and applying pointer arithmetic rules, it's the same as *(*(Feld+i)) . 顺便说一句,进一步讲,应用指针算术规则,它与*(*(Feld+i)) In any case, it's not what yo want 无论如何,这不是你想要的
  • *Feld[i].xxx is the same as *((Feld[i]).xxx) because . *Feld[i].xxx*((Feld[i]).xxx)因为. has a higher precedence than * . 具有比*高的优先级。 This will not compile because Feld[i] is not of type TFeld 因为Feld[i]不是TFeld类型, TFeld不会编译
  • Feld[i]->xxx is the same as (Feld[i])->xxx (because [] and -> have the same precedence but when both appear they are applied from left to right). Feld[i]->xxx(Feld[i])->xxx (因为[]->具有相同的优先级,但是当两者出现时,它们都是从左到右应用的)。 This is further the same as (*(Feld[i])).xxx . 这进一步与(*(Feld[i])).xxx And still not what you want. 仍然不是您想要的。

But lets visualize to understand the impact of applying dereferencing in a different order. 但是让我们可视化以了解以不同顺序应用取消引用的影响。 On top is what you need. 最重要的是您需要的。 The botom is what you should avoid: 根本是应避免的事情:

在此处输入图片说明

How to solve ? 怎么解决 ?

I suggest to change the commented out part into: 我建议将注释掉的部分更改为:

for (i=0;i<E.Groesse_X*E.Groesse_Y;i++)
{
    (*Feld)[i].Schiff_Versunken = false;
    (*Feld)[i].Schiff_Versunken = false;
    (*Feld)[i].Ueberprueft = false;
} 

Or if you don't like stars and partenheses: 或者,如果您不喜欢星星和黏附:

    Feld[0][i].Schiff_Versunken = false;
    Feld[0][i].Schiff_Versunken = false;
    Feld[0][i].Ueberprueft = false;

DOuble indirections are allways a little tricky. 双重定向总是有些棘手。 Whenever you're in doubt, add some parentheses. 如有疑问,请添加一些括号。

A final word: I assumed here that InitField() was called with a valid pointer to a pointer to TFeld , so that *Feld would without a doubt point to a pointer to TFeld . 最后一句话:我在这里假设InitField()是使用指向TFeld的有效指针来TFeld ,因此*Feld无疑会指向TFeld的指针。 If this would be the case, the pointer of you memory allocation could be written anywhere in memory, causing again memory corruption. 如果是这种情况,则您的内存分配指针可能会写入内存中的任何位置,从而再次导致内存损坏。 If in doubt, make an edit tou your question showing the calling code so that I can check. 如有疑问,请对您的问题进行编辑,以显示调用代码,以便我检查。

Feld is a pointer to an array of structs. Feld是指向结构数组的指针。 So you have to (1) dereference the pointer, then (2) index into the array, and finally (3) access the field inside the struct. 因此,您必须(1)取消引用指针,然后(2)索引数组,最后(3)访问struct内部的字段。

There are two ways to write this within your for loop; 有两种方法可以在for循环中编写此代码: which one you like better is a question of taste: 您更喜欢哪一个是口味问题:

(*Feld)[i].Schiff_Versunken = false;  // option 1
(*Feld + i)->Schiff_Versunken = false; // option 2

There is difference when you do it inside a function and directly . 在函数内部直接进行操作时会有所不同。 Because here Feld is a pointer to structure in test() , whereas it is a pointer to the pointer to the structure in initField() . 因为这里Feld是指向test()结构的指针,而它是指向initField()结构的指针。

When you used malloc(), the pointer to the structure got initialised, hence it didnt crashed when accessed inside test() . 当您使用malloc()时,指向该结构的指针已初始化,因此在test()内部访问时不会崩溃。 But the pointer to the pointer is still uninitialized, hence caused the seg fault in initField() . 但是指向该指针的指针仍未初始化,因此在initField()引起了seg错误。

So you have to allocate the double pointer correctly. 因此,您必须正确分配双指针。 Check this link for reference : C - dynamic memory allocation using double pointer 检查此链接以供参考: C-使用双指针的动态内存分配

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM