繁体   English   中英

重新分配:程序接收到的信号SIGTRAP,跟踪/断点陷阱

[英]realloc: Program received signal SIGTRAP, Trace/breakpoint trap

我正在开发一个存储任意长的联系人列表(姓名和电话号码)的程序。 条目存储在一个数组中,每次使用realloc函数添加新元素时,数组都会调整大小。 可以添加并显示第一个联系人。 但是,当我尝试添加第二个联系人时,程序崩溃并显示以下消息:

Program received signal SIGTRAP, Trace/breakpoint trap.
In ntdll!RtlZeroHeap () (C:\WINDOWS\SYSTEM32\ntdll.dll)

在我的编辑器中未设置任何断点。 调试器说问题出在包含realloc语句的行上。 如何解决此问题? 我在下面包含了代码的相关部分。

#define STRING_LENGTH 32

typedef struct entry_t {
    char name[STRING_LENGTH];
    char number[STRING_LENGTH];
} Entry;

void *add_entry(Entry*, int);

int main()
{
    int entry_count = 0;
    Entry *entries = calloc(1, sizeof(Entry));
    int choice = 0;

    while (1) {
        printf("Options:\n1) Add Entry\n2) Modify Entry\n3) Print Entries\n4) Exit\n\nSelect an option: ");
        scanf(" %d", &choice);
        switch (choice) {
        case 1:
            entries = add_entry(entries, entry_count++);
            break;
            // ...
        }
    }
}

void *add_entry(Entry *entries, int current_count)
{
    Entry entry;

    printf("Enter name: ");
    scanf(" %[^\n]s", entry.name);
    printf("Enter number: ");
    scanf(" %[^\n]s", entry.number);
    printf("\n");

    entries[current_count] = entry;
    return realloc(entries, sizeof(Entry) * (current_count + 1));
}

这里有一个逻辑问题。 您最初使用calloc为一个对象分配空间,然后使用计数等于0的方式调用add_entry

然后,在索引current_count处添加新条目,该条目此时为0。 然后,使用current_count + 1 (也为1)来调整内存的大小。因此,根本不需要调整内存的大小。

在下一次迭代中, entry_count为1,并在entries[1]处添加了一个新元素。 这就是问题所在,因为您目前仅剩一个对象的空间,所以您正在访问内存超出范围。

您应该通过current_count + 2进行重新分配,而不是通过current_count + 1重新分配,以便下一次迭代有空间将新元素放在内存的末尾。

void *add_entry(Entry *entries, int current_count)
{
    Entry entry;

    printf("Enter name: ");
    scanf(" %[^\n]s", entry.name);
    printf("Enter number: ");
    scanf(" %[^\n]s", entry.number);
    printf("\n");

    entries[current_count] = entry;
    return realloc(entries, sizeof(Entry) * (current_count + 2));  // <-- +2
}

请注意,您的current_count变量总是比分配的实际大小落后一步,这就是为什么您需要+2

编辑

还要注意,更自然的方法是先调整大小,然后再插入新对象。 因此,我将使用NULL初始化内存并执行以下操作:

int main()
{
    size_t entry_count = 0;
    Entry *entries = NULL, *tmp;
    int choice = 0;

    while (1) {
        printf("Options:\n1) Add Entry\n2) Modify Entry\n3) Print Entries\n4) Exit\n\nSelect an option: ");
        scanf(" %d", &choice);
        switch (choice) {
        case 1:
            tmp = add_entry(entries, &entry_count);
            if(tmp == NULL)
            {
                // error handling
                // entries still point to the old memory
                // could be useful in error handling

                free(entries);
                return 1;
            }

            entries = tmp;
            break;
            // ...
        }
    }
}

void *add_entry(Entry *entries, size_t *current_count)
{
    if(current_count == NULL)
        return NULL;

    Entry entry;

    printf("Enter name: ");
    scanf(" %[^\n]s", entry.name);
    printf("Enter number: ");
    scanf(" %[^\n]s", entry.number);
    printf("\n");

    if(entries == NULL)
        *current_count = 0;

    Entry *tmp = realloc(entries, (*current_count + 1) * sizeof *entries);

    if(tmp == NULL)
        return NULL;

    entries = tmp;

    entries[(*current_count)++] = entry;

    return entries;
}

请注意,重新realloc 计数变量的增量发生在同一函数中。 只有一切正常,您才应该增加计数器。 还要注意, entries是用NULL初始化的,因为realloc(NULL, size)等效于malloc(size)

暂无
暂无

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

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