我正在开发一个存储任意长的联系人列表(姓名和电话号码)的程序。这些条目存储在一个数组中,每次使用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));
}
答案 0 :(得分:1)
这里存在逻辑问题。您最初为一个对象分配空间
calloc
然后调用add_entry
,计数等于0。
然后在索引current_count
添加新条目,此时为0。
然后用current_count + 1
调整内存大小,这也是1.所以你是
根本没有调整记忆大小。
在下一次迭代中,entry_count
为1并在此处添加新元素
entries[1]
。这就是问题,你正在访问内存
边界,因为此时你仍然只有一个对象的空间。
而不是按current_count + 1
重新分配,您应该重新分配
current_count + 2
,以便下一次迭代有空间放置新的
内存末尾的元素。
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)
。