我可以在C中的结构中声明一个动态的结构引用数组吗?

时间:2012-10-16 06:42:54

标签: c pointers dynamic struct segmentation-fault

基本上我正在尝试构建一个cstrings的哈希结构,我可以将成员stringnode_ref *nodes重新分配给一个更大的维数组(malloc一个新的数组,重新哈希现有的值,并删除旧的当哈希开始填满时。

stringtable.c:

#include <stdio.h>
#include "stringtable.h"

struct stringnode{
    hashcode_t key;
    cstring value;
};

struct stringtable{
    size_t dim;
    size_t numEntries;
    stringnode_ref *nodes;
};

stringtable_ref new_stringtable(){
    size_t index = 0;
    stringtable_ref sTable = malloc(sizeof(struct stringtable));
    sTable->dim = 31;
    sTable->numEntries;
    sTable->nodes = malloc(31 * sizeof(struct stringnode));
    for( index = 0; index < 31; index++ ){
        sTable->nodes[index]->key = 0;
        sTable->nodes[index]->value = NULL;
    }
    return sTable;
}

stringtable.h:

#ifndef __STRINGTABLE_H__
#define __STRINGTABLE_H__

#include <stdlib.h>
#include <inttypes.h>

typedef char *cstring;

typedef uint32_t hashcode_t;

typedef stringtable *stringtable_ref;

typedef stringnode *stringnode_ref;

stringtable_ref new_stringtable();

#endif // __STRINGTABLE_H__

oc.c:

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

int main( int argc, char **argv ){
    stringtable_ref table = new_stringtable();
    return EXIT_SUCCESS;
}

编译:

gcc -g -O0 -Wall -Wextra -std=gnu99 -c stringtable.c
gcc -g -O0 -Wall -Wextra -std=gnu99 -c oc.c
gcc -g -O0 -Wall -Wextra -std=gnu99 -o oc stringtable.o oc.o

这一切都很好,没有错误,但在main()中声明stringtable_ref table = new_stringtable();时,程序会在sTable->nodes[index]->key = 0;处发生段错误。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

sTable->nodes = malloc(31 * sizeof(struct stringnode));
for( index = 0; index < 31; index++ ){
    sTable->nodes[index]->key = 0;

这就是问题:发生段错是因为你没有为sTable-nodes[index]分配内存,所以它可能是垃圾(当我在OS X下检查GDB上的代码时,它实际上是NULL

解决方案:将以下行添加为for循环正文的第一行:

sTable->nodes[index] = malloc(sizeof(*(sTable->nodes[index])));

答案 1 :(得分:0)

您将nodes的{​​{1}}元素定义为stringtable的指针,即指向stringnode_ref的指针。由于您执行struct stringnode,因此您计算sTable->nodes = malloc(31 * sizeof(struct stringnode));的大小,就好像它是指向sTable->nodes的指针(它不是)。

可能,你想要像这样定义字符串:

struct stringnode

然后,您可以使用

初始化节点
struct stringtable{
  size_t dim;
  size_t numEntries;
  stringnode_ref nodes;
};

以下是正确编译的整个代码,并且不显示valgrind的内存错误。编译sTable->nodes[index].key = 0; sTable->nodes[index].value = NULL; ;使用gcc -Wall --pedantic -o ttt -g ttt.c检查内存错误。请注意valgrind --tool=memcheck ./ttt如何使用并在您自己的代码中实现它。

sizeof()

P.S。您编辑的帖子中描述的编译代码的尝试导致以下结果:

#include <stdlib.h>

typedef char *cstring;

struct stringnode{
    int key;
    cstring value;
};

typedef struct stringnode *stringnode_ref;

struct stringtable{
    size_t dim;
    size_t numEntries;
    stringnode_ref nodes;
};

typedef struct stringtable *stringtable_ref;

stringtable_ref new_stringtable(){
    size_t index = 0;
    stringtable_ref sTable = malloc(sizeof( *sTable ) ) ;
    sTable->dim = 31;
    sTable->nodes = malloc(31 * sizeof( *sTable->nodes ) ) ;
    for( index = 0; index < 31; index++ ){
        sTable->nodes[index].key = 0;
        sTable->nodes[index].value = NULL;
    }
    return sTable;
}


int main(int argc, char *argv[]) {
  stringtable_ref table = new_stringtable();
  exit( EXIT_SUCCESS ) ;
}