【问题标题】:Difficulties with understanding reallocating using malloc理解使用 malloc 重新分配的困难
【发布时间】:2015-04-26 00:49:44
【问题描述】:

我正在尝试使用malloc 而不是realloc 来增加我的collection 结构的大小。恐怕我在分配变量时犯了错误,因为我得到了:

malloc: *** error for object 0x7fd46b404ac8: pointer being freed was not allocated

如果您能给我一个有用的提示,我将不胜感激。

void increaseCollectionSize(){
  collection.size = (collection.size + 1) * REALLOCATE_MODIFIER;
  char **increasedCollection = malloc(sizeof(char *) * collection.size);
  char **increasedHead = increasedCollection;
  for(int i = 0; i < collection.numberOfWords; i++){
    *increasedCollection = *collection.words;
    increasedCollection++;
    collection.words++;
  }
  free(collection.words); // I'm getting error here.
  collection.words = increasedHead;
}

typedef struct Collection{
  char **words;
  size_t numberOfWords;
  size_t size;
} Collection;

【问题讨论】:

  • collection.words 分配在哪里?
  • 没有有用的调试器的 c 编程就像在鲨鱼水中潜水,腿上绑着一头死去流血的牛。
  • @user2225104 在我十多年的实践中,最有用的调试器是 fprintf(stderr) 跟踪,尤其是在线程/异步调试中。无论如何,除非他意识到指针不再指向块的开始,否则他无法得到它。 “一个有用的”调试器如何帮助解决这个逻辑错误?
  • @user3125367 在我 3 年以上的实践中,最有用的调试器是调试器以及编写(单元)可测试代码。如果您养成使用调试器单步执行新代码两次的习惯,一次关注控制流,一次关注数据值,您很快就会发现逻辑错误。我强烈推荐的一本书“Writing Solid Code”中也宣传了这个技巧。在完整的运行时环境中查找逻辑错误只是浪费时间。
  • @user3125367 所要做的就是在客户处坐上几次,然后在他们回头看时发现那里有一个愚蠢的虫子。然后,随后不得不浪费时间进行令人沮丧的责骂和讨论。几次之后,人们宁愿把时间花在适当的测试上,也不愿花在令人沮丧的社交互动上;)

标签: c memory-leaks malloc runtime-error


【解决方案1】:

你释放了collection.words的最终值,它是一个指向原始内存块末尾的指针(由于循环中的++)。

void increaseCollectionSize(){
    collection.size = (collection.size + 1) * REALLOCATE_MODIFIER;
    char **increasedCollection = malloc(sizeof(char *) * collection.size);
    char **increasedHead = increasedCollection;
    char **originalWords = collection.words; // save a pointer
    for(int i = 0; i < collection.numberOfWords; i++){
        *increasedCollection = *collection.words;
        increasedCollection++;
        collection.words++;
    }
    free(originalWords); // now ok
    collection.words = increasedHead;
}

或者,降低复杂性:

void increaseCollectionSize() {
    collection.size = (collection.size + 1) * REALLOCATE_MODIFIER;
    char **increasedCollection = malloc(sizeof(char *) * collection.size);
    assert(increasedCollection != NULL); // explicitly abort() on malloc() error

    for (size_t i = 0; i < collection.numberOfWords; i++)
        increasedCollection[i] = collection.words[i];

    free(collection.words);
    collection.words = increasedCollection;
}

【讨论】:

  • 非常感谢!我可以问一个问题吗? FIXME assert 是什么意思?
  • 如果你没有在 malloc() 之后写 sml "malloc check needed" 注释,你肯定会得到一堆你应该在答案中提到的 cmets。这就是stackoverflow.com的本质;)与“不要强制转换malloc”和“不要(sizeof(char)* x)”相同。添加了一个示例。 @MateuszPiotrowski
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多