【问题标题】:What's the problem with this code? [hashtable in C]这段代码有什么问题? [C中的哈希表]
【发布时间】:2011-06-06 22:39:31
【问题描述】:

我正在实现一个哈希表。以下是我的初始化函数。 我收到一些我不明白为什么的错误。我还引用了 valgrind 所说的话。

 typedef struct HashTable
    {
     int size ;  
     struct List *head; 
     struct List *tail;     
    }HashTable;

    typedef struct List
    {
     char *number;
     char *name;
     int time;
     struct List *next;     
    }List;

    #define size_of_table 211

    HashTable *createHashTable(void)
    {
     HashTable *new_table = malloc(sizeof(*new_table)*size_of_table); //line 606

     if (new_table == NULL)
     { return NULL;
     }

     int i=0;
     for(i; i<size_of_table; i++)
     { 
      new_table[i].size=0;
      new_table[i].head=NULL;
      new_table[i].tail=NULL;
     }
     return NULL;
    }
Invalid write of size 8
==7738==    at 0x401707: createHashTable (project2.c:617)
==7738==    by 0x401AF6: main (project.c:739)
==7738==  Address 0x51996e0 is 8 bytes after a block of size 1,688 alloc'd
==7738==    at 0x4C25153: malloc (vg_replace_malloc.c:195)
==7738==    by 0x401698: createHashTable (project2.c:606)
==7738==    by 0x401AF6: main (project.c:739)
==7738== 
==7738== 
==7738== 141 errors in context 3 of 4:
==7738== Invalid write of size 8
==7738==    at 0x4016E8: createHashTable (project2.c:616)
==7738==    by 0x401AF6: main (project.c:739)
==7738==  Address 0x51996d8 is 0 bytes after a block of size 1,688 alloc'd
==7738==    at 0x4C25153: malloc (vg_replace_malloc.c:195)
==7738==    by 0x401698: createHashTable (project2.c:606)
==7738==    by 0x401AF6: main (project.c:739)

【问题讨论】:

  • @SLaks。我已经在程序开始时定义了它。这是一个整数。
  • memset(3),或bzero(3)

标签: c hashtable


【解决方案1】:

确定这是您正在测试的代码吗? 1688 个字节分为 211 个数组元素,每个元素为 8 个字节。

现代环境不太可能只为包含 int 和两个指针的结构提供 8 个字节。


通过测试,如下代码:

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

typedef struct HashTable {
    int size ;
    struct List *head;
    struct List *tail;
} HashTable;

typedef struct List {
    char *number;
    char *name;
    int time;
    struct List *next;
} List;

#define size_of_table 211

HashTable *createHashTable(void) {
    HashTable *new_table = malloc(sizeof(*new_table)*size_of_table); //line 606
    printf ("%d\n", sizeof(*new_table));
    printf ("%d\n", sizeof(new_table));
    if (new_table == NULL) {
        return NULL;
    }

    int i=0;
    for(i; i<size_of_table; i++) {
        new_table[i].size=0;
        new_table[i].head=NULL;
        new_table[i].tail=NULL;
    }
    return new_table;
}

int main(void) {
    HashTable *x = createHashTable();
    free (x);
    return 0;
}

输出:

==3569== Memcheck, a memory error detector
==3569== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==3569== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==3569== Command: ./qq
==3569== 
12
4
==3569== 
==3569== HEAP SUMMARY:
==3569==     in use at exit: 0 bytes in 0 blocks
==3569==   total heap usage: 1 allocs, 1 frees, 2,532 bytes allocated
==3569== 
==3569== All heap blocks were freed -- no leaks are possible
==3569== 
==3569== For counts of detected and suppressed errors, rerun with: -v
==3569== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 8)

当您通过系统上的 valgrind 运行该程序时,该程序会为您提供什么?

我在上面提供的代码还解决了您在成功时返回 NULL 的问题(明确的内存泄漏)。您在函数中的最终返回不应返回 NULL,它应该是:

    return new_table;

根据我提供的示例代码中您的24,8 输出,确保您真的使用:

    HashTable *new_table = malloc(sizeof(*new_table)*size_of_table); //line 606

而不是:

    HashTable *new_table = malloc(sizeof(new_table)*size_of_table); //line 606

后者将使用8 的指针大小而不是24 的结构大小,当我这样做时,我得到:

==3637== Memcheck, a memory error detector
==3637== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==3637== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==3637== Command: ./qq
==3637== 
12
4
==3637== Invalid write of size 4
==3637==    at 0x80484CD: createHashTable (in /home/allan/qq)
==3637==    by 0x8048509: main (in /home/allan/qq)
==3637==  Address 0x419a374 is 0 bytes after a block of size 844 alloc'd
==3637==    at 0x4024F20: malloc (vg_replace_malloc.c:236)
==3637==    by 0x8048465: createHashTable (in /home/allan/qq)
==3637==    by 0x8048509: main (in /home/allan/qq)
==3637== 
==3637== Invalid write of size 4
==3637==    at 0x80484E3: createHashTable (in /home/allan/qq)
==3637==    by 0x8048509: main (in /home/allan/qq)
==3637==  Address 0x419a378 is 4 bytes after a block of size 844 alloc'd
==3637==    at 0x4024F20: malloc (vg_replace_malloc.c:236)
==3637==    by 0x8048465: createHashTable (in /home/allan/qq)
==3637==    by 0x8048509: main (in /home/allan/qq)
==3637== 
==3637== Invalid write of size 4
==3637==    at 0x80484B8: createHashTable (in /home/allan/qq)
==3637==    by 0x8048509: main (in /home/allan/qq)
==3637==  Address 0x419a37c is 8 bytes after a block of size 844 alloc'd
==3637==    at 0x4024F20: malloc (vg_replace_malloc.c:236)
==3637==    by 0x8048465: createHashTable (in /home/allan/qq)
==3637==    by 0x8048509: main (in /home/allan/qq)
==3637== 
==3637== 
==3637== HEAP SUMMARY:
==3637==     in use at exit: 0 bytes in 0 blocks
==3637==   total heap usage: 1 allocs, 1 frees, 844 bytes allocated
==3637== 
==3637== All heap blocks were freed -- no leaks are possible
==3637== 
==3637== For counts of detected and suppressed errors, rerun with: -v
==3637== ERROR SUMMARY: 422 errors from 3 contexts (suppressed: 13 from 8)

如果您确定您使用的是 24 值,请放置以下行:

printf ("%d\n", sizeof(*new_table)*size_of_table);

malloc 行之后,看看它输出了什么。

【讨论】:

  • 说实话,我只是先测试了一个随机数。 ://
  • 您确定您的 malloc 语句不是 sizeof(new_table)*size_of_table(即指针的大小而不是内容的大小)吗?那将是 8 而不是 24。
  • 不,我检查过了。它是:malloc(sizeof(*new_table)*size_of_table);
  • 有没有这种内存被分配的情况?导致 valgring 给出:搜索指向 1 个未释放块的指针
  • 它仍然保持分配的块是 1688 字节?尝试在 malloc 中使用sizeof(HashTable) 而不是sizeof(*new_table)(幽默我)。然后,just 使用我上面在单个源文件中提供的代码,并告诉我们确切的输出。这应该可以消除您问题中我还不知道的任何棘手方面:-)
【解决方案2】:

对我来说很好用。我添加了const int size_of_table = 12 并从main 调用了createHashTable()

$ valgrind ./a.out 
==30237== Memcheck, a memory error detector
==30237== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==30237== Using Valgrind-3.6.0.SVN and LibVEX; rerun with -h for copyright info
==30237== Command: ./a.out
==30237== 
--30237-- ./a.out:
--30237-- dSYM directory is missing; consider using --dsymutil=yes
==30237== 
==30237== HEAP SUMMARY:
==30237==     in use at exit: 376 bytes in 2 blocks
==30237==   total heap usage: 2 allocs, 0 frees, 376 bytes allocated
==30237== 
==30237== LEAK SUMMARY:
==30237==    definitely lost: 288 bytes in 1 blocks
==30237==    indirectly lost: 0 bytes in 0 blocks
==30237==      possibly lost: 0 bytes in 0 blocks
==30237==    still reachable: 88 bytes in 1 blocks
==30237==         suppressed: 0 bytes in 0 blocks
==30237== Rerun with --leak-check=full to see details of leaked memory
==30237== 
==30237== For counts of detected and suppressed errors, rerun with: -v
==30237== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
$ 

【讨论】:

  • Berger 正如你所说,我也试过 12,但还是一样!
猜你喜欢
  • 1970-01-01
  • 2016-10-23
  • 1970-01-01
  • 2013-04-30
  • 2015-04-25
  • 2018-09-09
相关资源
最近更新 更多