【问题标题】:memset clearing what it's not supposedmemset 清除它不应该的东西
【发布时间】:2016-12-10 18:27:26
【问题描述】:

我有一个服务器 - 客户端程序,我可以添加或删除用户。当达到最大用户数(10)时,删除一个用户时出现错误。

这是删除用户的部分功能:

int i;
int confirmacao = 0;
msg_t msg;
char cliname[10];
if (strlen(estrutura.id) == 3) {
    for (i = 0; memoria->x[i].id[0] != '\0'; ++i) {
        if (strcmp(estrutura.id, memoria->x[i].id) == 0) {
            confirmacao = 1;
            for (; memoria->x[i].id[0] != '\0'; ++i) {
                memoria->x[i] = memoria->x[i + 1];
            }
            // I think the problem is with this memset
            memset(memoria->x[i].id, '\0', sizeof(memoria->x[i].id));
            printf("IA antes de decrementar: %i\n", memoria->ia);
            memoria->ia--;
            printf("Ia depois: %i\n", memoria->ia);
            break;
        }
    }
} else {
    ...
}

Here is the print from gdb

memoria->ia 应该减一,我可以弄清楚为什么 memset 将其设置为零。

memoria 是这个结构的全局指针:

typedef struct mmap_uti_s {
    uti_t x[NUTI];
    int ia;
} mmap_uti_t;

而uti_t就是这个结构:

typedef struct uti_s {
    char id[NDIG + 1];
    char nome[NDIM + 1];
    char portas[NPOR + 1];
} uti_t;

【问题讨论】:

    标签: c


    【解决方案1】:

    复制前一个元素后,您未能重置最后一个元素,因为您在测试数组末尾之前增加了i。此外,正如您正确指出的那样,您必须始终在到达数组末尾之前停止复制。

    您应该将嵌套 for 循环中的测试更改为:

    for (; i + 1 < 10 && memoria->x[i + 1].id[0] != '\0'; i++)
    

    如果数组已满,您还应该更改主循环中的测试以在数组末尾停止扫描。

    虽然不是绝对必要,但最好在复制阶段使用不同的索引,以避免修改当前循环的索引。

    清除整个结构,而不仅仅是 id 成员,似乎也更可取。

    这里是修改后的代码:

    int i, j;
    int confirmacao = 0;
    msg_t msg;
    char cliname[10];
    if (strlen(estrutura.id) == 3) {
        for (i = 0; i < 10 && memoria->x[i].id[0] != '\0'; ++i) {
            if (strcmp(estrutura.id, memoria->x[i].id) == 0) {
                confirmacao = 1;
                for (j = i; j + 1 < 10 && memoria->x[j].id[0] != '\0'; ++j) {
                    memoria->x[j] = memoria->x[j + 1];
                }
                // I think the problem is with this memset
                memset(&memoria->x[j], 0, sizeof(memoria->x[j]));
                printf("IA antes de decrementar: %i\n", memoria->ia);
                memoria->ia--;
                printf("Ia depois: %i\n", memoria->ia);
                break;
            }
        }
    } else {
        ...
    }
    

    【讨论】:

    • 非常感谢您,我需要很长时间才能发现这一点!
    • 它按您说的方式工作,但是在考虑了更多之后,如果我这样做,如果数组已满,则在最后一个循环中它将执行 memoria-&gt;x[9] = memoria-&gt;x[10]; 女巫不存在。还是我想错了?
    • 我认为条件应该是i+2,然后是memset中的i+1
    • @Sebastiao:您的推理是正确的,测试还应该考虑最大有效偏移量。如果memoria-&gt;x 中有 10 个条目,请使用 for (; i &lt; 10 - 1 &amp;&amp; memoria-&gt;x[i + 1].id[0] != '\0'; i++)
    • @Sebastiao:外部 for 循环中缺少相同的测试。在整个表中搜索不存在的id 会调用未定义的行为,因为您继续扫描超出数组的末尾。我更新了答案。
    猜你喜欢
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 2022-10-18
    • 2016-02-23
    • 2010-10-13
    相关资源
    最近更新 更多