C中的结构分配导致内存覆盖(我认为)

Mat*_*ong 4 c arrays malloc struct

我以为我理解这些东西,但我很难过.

给定一个结构声明为:

typedef struct _Thing {
  uint32_t type;
  struct _Thing *children;
  unsigned long childCount;
  char *description;

  union {
    uint32_t thirtyTwoBitValue;
    char *nameValue;
  } data;

} Thing;
Run Code Online (Sandbox Code Playgroud)

我有一个方法重新分配一个数组,以适应添加一个新的Thing对象.它看起来像这样:

void AddTopLevelThing(Thing *thing)
{
  Thing *oldThings = things;
  things = malloc(sizeof(Thing) * thingCount +1);

  // Add any existing things to the new array
  for (int i = 0; i < thingCount; ++i) {
    things[i] = oldThings[i];
  }

  // Add the newest thing to the new array
  things[thingCount] = *thing;

  // Increment the thing count
  thingCount++;
}
Run Code Online (Sandbox Code Playgroud)

注意:thing和thingCount是全局变量.不要怪胎.;-)哦,我也意识到这是泄漏.一次有一个问题......

为了创建我的Thing对象,我创建了一个初始化函数.它看起来像这样:

Thing* CreateThingWithDescription(char *description)
{
  Thing *thing = malloc(sizeof(Thing));
  if (thing == NULL) {
    printf("Bad thing!, Bad!\n");
    return NULL;
  }

  // Initialize everything in the structure to 0
  memset(thing, 0, sizeof(Thing));

  thing->children = NULL;
  thing->description = strdup(description);

  return thing;
}
Run Code Online (Sandbox Code Playgroud)

为了使事情复杂化(没有双关语),Thing对象有一个子数组,当添加新对象时,它们会被重新分配(增长).它看起来像这样:

void AddChildThingToThing(Thing *parent, Thing *child)
{
  Thing *oldChildren = parent->children;
  parent->children = malloc(sizeof(Thing) * parent->childCount + 1);
  if (parent->children == NULL) {
    printf("Couldn't allocate space for thing children.\n");
    parent->children = oldChildren;
    return;
  }

  // Add any existing child things to the new array
  for (int i = 0; i < parent->childCount; ++i) {
    parent->children[i] = oldChildren[i];
  }

  // Add the newest child thing to the new array
  parent->children[parent->childCount] = *child;  

  // Increment the child count
  parent->childCount = parent->childCount + 1;
}
Run Code Online (Sandbox Code Playgroud)

无论如何,我很难搞清楚为什么当我完成创建结构并添加子结构时,即使我在创建时验证了它们的创建(在调试器中),它们也经常被清零.当我的主要代码完成运行时,我应该有一个树结构,但它只是一个我不认识或理解的一堆错误的值 - 这就是我相信事情被覆盖的原因.

无论如何,我希望我只是忽略了一些简单的事情.

如果你想看看我如何构建我的对象层次结构,这是我的主要内容:

int main(int argc, const char * argv[])
{
  things = NULL;
  thingCount = 0;

  Thing *thing = CreateThingWithDescription("This is thing 1");
  SetThingName(thing, "Willy Johnson");
  AddTopLevelThing(thing);
  Thing *child = CreateThingWithDescription("This is child thing 1");
  SetThingName(child, "Willy's Son");
  AddChildThingToThing(thing, child);
  child = CreateThingWithDescription("This is child thing 2");
  SetThingName(child, "Willy's Daughter");
  AddChildThingToThing(thing, child);

  thing = CreateThingWithDescription("This is thing 2");
  SetThingValue(thing, 700);
  AddTopLevelThing(thing);
  child = CreateThingWithDescription("This is child thing 3");
  SetThingValue(child, 1024);
  AddChildThingToThing(thing, child);

  for (int i = 0; i < thingCount; ++i) {
    PrintThing(&things[i]);
  }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

注意:这只是一个演示项目,以确定发生了什么.

nul*_*ptr 6

您需要在函数中多分配一个结构,而不是一个字节AddTopLevelThing:

things = malloc(sizeof(Thing) * (thingCount+1));
Run Code Online (Sandbox Code Playgroud)

此外,重新分配后,您不会释放旧的内存块.并且最好使用realloc('realloc'关心复制旧数据和释放旧内存;它有时也可以执行"就地重新分配",效率更高):

void AddTopLevelThing(Thing *thing) {
    thingCount++;
    things = realloc(things, sizeof(Thing) * thingCount);
    things[thingCount-1] = *thing;
}
Run Code Online (Sandbox Code Playgroud)

  • 好的捕获,同样的问题在这里:`malloc(sizeof(Thing)*parent-> childCount + 1)`. (2认同)
  • 同样为了记录,在进行这种类型的数组扩展时,最有效的方法是将数组的大小加倍,而不是添加一个.除了`thingCount`之外还存储`maxThings`并使用`maxThings*= 2调整大小; realloc(things,sizeof(Thing)*maxThings); 事[++ thingCount] =*thing;` (2认同)