【问题标题】:Strange error with realloc in VS 2010VS 2010 中 realloc 的奇怪错误
【发布时间】:2011-08-25 14:18:06
【问题描述】:

我有一个代码:

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>

typedef struct NOTE
{
    char NAME[50],  
         TELE[30];  
    int  BDAY[3];   
} NOTE;

void AddNote(NOTE * Notes, int NotesCount, NOTE * Temp)
{
    Notes = (struct NOTE *) realloc(Notes, (NotesCount + 1) * sizeof(struct NOTE));
    memcpy(Notes + NotesCount, Temp, sizeof(struct NOTE));
}

void main()
{
    int NotesCount = 0, i = 0, f = 0;
    int a;
    NOTE * BLOC_NOTE, * Temp;

    Temp = (struct NOTE *) malloc(sizeof(struct NOTE));
    BLOC_NOTE = (struct NOTE *) calloc(0, sizeof(struct NOTE));

    for(i = 0; i < 4; i++)
    {
        ShowInputDialog(Temp);
        AddNote(BLOC_NOTE, NotesCount++, Temp);     
    }
}

在 BLOC_NOTE 的第三个元素上,程序在

处崩溃
Notes = (struct NOTE *) realloc(Notes, (NotesCount + 1) * sizeof(struct NOTE));

VS 告诉我操作系统 Windows 启动了断点...

怎么了?

编辑
将代码从评论移到这里

void ShowInputDialog(NOTE * Temp) 
{ 
    printf("Name: "); 
    scanf("%s", (*Temp).NAME); 
    printf("Telephone: "); 
    scanf("%s", (*Temp).TELE); 
    printf("Birthday: "); 
    scanf("%d\.%d\.\%d", (*Temp).BDAY, ((*Temp).BDAY + 1), ((*Temp).BDAY + 2));
 }

【问题讨论】:

  • 看起来没问题,所以错误肯定在其他地方,比如ShowInputDialog。那有什么作用?
  • void ShowInputDialog(NOTE * Temp) { printf("Name: "); scanf("%s", (*Temp).NAME); printf("Telephone: "); scanf("%s", (*Temp).TELE); printf("Birthday: "); scanf("%d\.%d\.\%d", (*Temp).BDAY, ((*Temp).BDAY + 1), ((*Temp).BDAY + 2)); }
  • 我不确定我能否破译您的日期格式字符串。它究竟应该是什么意思?如果输入不完全符合预期会发生什么?
  • 我的编译器抱怨 \.也!它可能应该是“%d/%d/%d”或“%d.%d.%d”,这取决于你如何写日期。

标签: c visual-studio struct realloc


【解决方案1】:

需要检查从 malloc( )、calloc( ) 和 realloc( ) 返回的指针值。你在哪里做过这些检查?

【讨论】:

  • 我可以在输入后打印这些值。有了他们,一切都井井有条。但是程序在第三次重新分配时崩溃了……(或 VS)
【解决方案2】:

这是错误的:

void AddNote(NOTE * Notes, int NotesCount, NOTE * Temp)
{
    Notes = (struct NOTE *) realloc(Notes, (NotesCount + 1) * sizeof(struct NOTE));
    memcpy(Notes + NotesCount, Temp, sizeof(struct NOTE));
}

Notes 是保存第一个 NOTE 对象地址的局部变量。但是当函数返回时,该值就丢失了。您必须返回新值,因为 C 没有引用:

NOTE* AddNote(NOTE * Notes, int NotesCount, NOTE * Temp)
{
    Notes = (struct NOTE *) realloc(Notes, (NotesCount + 1) * sizeof(struct NOTE));
    memcpy(Notes + NotesCount, Temp, sizeof(struct NOTE));
    return Notes;
}

for(i = 0; i < 4; i++)
{
   ShowInputDialog(Temp);
   BLOC_NOTE = AddNote(BLOC_NOTE, NotesCount++, Temp);     
}

在 C++ 中这已经足够了:

void AddNote(NOTE * &Notes, int NotesCount, NOTE * Temp)
{
    Notes = (struct NOTE *) realloc(Notes, (NotesCount + 1) * sizeof(struct NOTE));
    memcpy(Notes + NotesCount, Temp, sizeof(struct NOTE));
}

【讨论】:

  • 另一种解决方法是将NOTE** 传递给AddNote()(并相应地调整使用)。
【解决方案3】:

好的,现在我想通了。

void AddNote(NOTE * Notes, int NotesCount, NOTE * Temp)
{
    Notes = (struct NOTE *) realloc(Notes, (NotesCount + 1) * sizeof(struct NOTE));
    memcpy(Notes + NotesCount, Temp, sizeof(struct NOTE));
}

AddNote 中,参数NotesBLOC_NOTE 的副本。如果 realloc 成功扩展块,那没关系。但是,如果 realloc 分配一个新块(并复制那里的所有内容),BLOC_NOTE 突然无效,因为它现在指向已释放的内存。

下次调用 AddNode 时,内存调试器显然会检测到这一点。

【讨论】:

    猜你喜欢
    • 2018-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-27
    • 1970-01-01
    • 2016-07-30
    • 2018-10-22
    相关资源
    最近更新 更多