【问题标题】:Change global variable value using pointer使用指针更改全局变量值
【发布时间】:2014-01-27 16:27:57
【问题描述】:

我的代码有问题。我的全局变量没有改变。我已将其地址分配给一个指针。这是我的结构初始化:

    struct PortData {
        int port;
        int sent;
        int received;
        int total;
        struct PortData *Next;
    };

    struct IPData {
        time_t timestamp;
        uint32_t ip;
        struct PortData Record;
    };

这是我返回地址的函数:

    inline struct IPData *FindIp(uint32_t ipaddr) {
    unsigned int counter;

    for (counter = 0; counter < IpCount; counter++)
        if (IpTable[counter].ip == ipaddr)
            return (&IpTable[counter]);

    if (IpCount >= IP_NUM) {
        syslog(LOG_ERR, "IP_NUM is too low, dropping ip....");
        return (NULL);
    }

    memset(&IpTable[IpCount], 0, sizeof (struct IPData));
    IpTable[IpCount].ip = ipaddr;
    return (&IpTable[IpCount++]); 
    }

这里把指针赋值给IpTable的地址:

    struct IPData *ptrIPData;
    for (Count = 0; Count < SubnetCount; Count++) {
        if (SubnetTable[Count].ip == (iph->saddr & SubnetTable[Count].mask)) {
            ptrIPData = FindIp(iph->saddr);
            Credit(&(ptrIPData->Record), iph, tcph, srcip);          
        }    
        if (SubnetTable[Count].ip == (iph->daddr & SubnetTable[Count].mask)) {
            ptrIPData = FindIp(iph->daddr);
            Credit(&(ptrIPData->Record), iph, tcph, dstip);
        }

    }

这是我的 Credit() 函数:

inline void Credit(struct PortData *pordt, struct iphdr *iph, struct tcphdr *tcph, struct in_addr sipaddr) {

    unsigned int sport, dport;

    memset(&source, 0, sizeof (source));
    source.sin_addr.s_addr = iph->saddr; //init source ip
    sport = ntohs(tcph->source);

    memset(&dest, 0, sizeof (dest));
    dest.sin_addr.s_addr = iph->daddr; //init dest ip
    dport = ntohs(tcph->dest);

    packet_size = ntohs(iph->tot_len);
    if (iph->protocol == 6) //6 is protocol TCP
    {
        prev = portdt;
        int sameport = 0;
        while (prev != NULL) {
            if (dport == prev->port || sport == prev->port) {
                if (dport == prev->port) {
                    prev->sent += packet_size;
                }
                if (sport == prev->port) {
                    prev->received += packet_size;
                }
                sameport = 1;
                break;
            }            
        }

        if (sameport == 0) {
            printf("create new node\n");
            newnode = (struct PortData*) malloc(sizeof (struct PortData));
            newnode->received = 0;
            newnode->sent = 0;
            if (sipaddr.s_addr == source.sin_addr.s_addr) {
                if (tcph->syn == 1 || tcph->ack == 1) {
                    newnode->port = dport;
                    newnode->sent = packet_size;
                }
            }
            if (sipaddr.s_addr == dest.sin_addr.s_addr) {
                if (tcph->syn == 1 && tcph->ack == 1) {
                    newnode->port = sport;
                    newnode->received = packet_size;
                }
            }
            newnode->Next = portdt;
            portdt = newnode;
        }//==end-sameport==
    }//iph->protocol//

    prev = portdt;
    while (prev != NULL) {
        fprintf(logfile, "ip = %s port=%d sent=%d bytes received=%d bytes\n", inet_ntoa(sipaddr), prev->port, prev->sent, prev->received);
        prev = prev->Next;
    }
}

我假设在执行Credit() 函数后,Iptable[Counter].Record 的值必须更改,因为ptrIPData 指向它的地址。但为什么没有呢?

【问题讨论】:

  • 一些离题的cmets:不要强制转换malloc返回的指针。您可以通过移动避免两次写入if (tcph-&gt;syn == 1 &amp;&amp; tcph-&gt;ack == 1)。变量命名保持一致:CamelCase 还是更低?
  • 你查过iph-&gt;protocol真的是6吗?
  • while (prev != NULL) 如果在进入循环之前prev 不是NULL,则while (prev != NULL) 可能会变成无限循环,因为prev 永远不会在循环内部分配。
  • 我的Credit() 功能正常工作。执行此函数时,发送和接收的数量增加了packet_size。好的,我会将prev 赋值为NULL。
  • 哦,抱歉,您似乎尝试在链接列表的开头插入新值,在这种情况下,请尝试@David 的回答。

标签: c pointers struct global-variables assign


【解决方案1】:

您应该将 line 替换为:而不是 portdt = newnode;

portdt->port = newnode->port;
portdt->sent = newnode->sent;
portdt->received = newnode->received;
portdt->total = newnode->total;
portdt->Next = newnode->Next;

就像@David 说的,portdt = newnode; 只是改变局部变量,而不是改变portdt 指出的东西。

【讨论】:

    【解决方案2】:

    您正在尝试将新项目插入到链接列表Record。你试图通过写来做到这一点:

    newnode = (struct PortData*) malloc(sizeof (struct PortData));
    // initialise newnode
    newnode->Next = portdt;
    portdt = newnode;
    

    问题在于portdt 是包含IPData 结构的Record 成员地址的局部变量。因此,分配给局部变量portdt 并没有实现函数外可见的任何内容。

    您需要进行一些更改。首先,您需要将struct PortData Record 更改为struct PortData *Record。这是列表的头指针,它必须声明为指向节点的指针,而不是像您所做的那样作为节点值。

    然后你仍然将&amp;Record 传递给Credit,但现在portdtstruct PortData **Record 类型。于是节点插入赋值就变成了

    newnode = malloc(sizeof (struct PortData));
    // initialise newnode
    newnode->Next = *portdt;
    *portdt = newnode;
    

    您的代码还有其他问题。我不会尝试将它们全部列出,但这是我所看到的:

    • 不要转换malloc的返回值。
    • 您应该检查malloc 的返回值是否有错误。
    • prev 声明为局部变量,而不是当前看起来的全局变量。

    【讨论】:

    • 感谢您的解释。那么我需要声明**prev 而不是*prev 吗?我需要使用prevportdt 中搜索节点。如果我声明了**prev,我不知道while(prev != NULL) 的下一个语法,访问dport = prev-&gt;port 等。我是新来使用指向这样的指针的指针。
    猜你喜欢
    • 2019-05-08
    • 2021-11-11
    • 1970-01-01
    • 2014-05-18
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多