Q:

Manipulating array results in segfault?

I'm writing a C application which involves parsing a text file (in a format called VSM, hence the names below) into a tree structure. The designer of the format calls it a tagged tree. Each node has some key-value pairs (or attributes) and child nodes.
Below are the struct and function in question:
vsm.h:
struct vsm_node {
    int                   numchildren;
    struct vsm_attribute *attrs   [36];
    struct vsm_node      *children[8];
};

void vsm_addchild(struct vsm_node *node, struct vsm_node *child);

vsm.c:
#include "vsm.h"

void vsm_addchild(struct vsm_node *node, struct vsm_node *child)
{
    node->children[node->numchildren] = child;
    ++(node->numchildren);
}

Why is it that when I call vsm_addchild it produces a segfault?
Sorry if this is a stupid question, but I just really suck at plain C. Especially if it has to do with pointers and memory management.

EDIT to include the code to make the call:
#include <stdio.h>
#include "vsm.h"

void vsm_parse(struct vsm_node *tree, FILE *fp, char *name)
{
    struct vsm_node *this     = tree;

    int ch;
    while ((ch = fgetc(fp)) != 0) {
        ...
        else if (ch == '{') {
            struct vsm_node *node;
            vsm_initnode(node);
            vsm_addchild(this, node);
            this = node;
            ...
        ...

EDIT: Added the vsm_initnode function, but I don't know if I'm doing it right.
void vsm_initnode(struct vsm_node *node)
{
    node              = malloc(     sizeof(struct vsm_node *));
    node->attrs       = malloc(36 * sizeof(struct vsm_attribute *));
    node->children    = malloc( 8 * sizeof(struct vsm_node *));
    node->numchildren = 0;

    int i;
    for (i = 0; i < 36; ++i)
        node->attrs[i] = NULL; /* unnecessary? */
    for (i = 0; i  < 8; ++i)
        node->children[i] = NULL;
}

void vsm_addchild(struct vsm_node *node, struct vsm_node *child)
{
    node->children[node->numchildren] = child;
    ++(node->numchildren);
}

gdb output:
Program received signal SIGSEGV, Segmentation fault.
vsm_addchild (node=0x28, child=0x7541612d <msvcrt!_atodbl_l+2294>) at vsm.c:62
62              node->children[node->numchildren] = child;

A:

Here are reasons this code might segfault:

node is NULL, uninitialized, pointing to freed memory, or
node->children is NULL, uninitialized, pointing to freed memory, or
node->numchildren is greater than the allocated size of node->children

Make sure the calling code:

Allocates node
allocates node->children
sets node->numchildren
passed in the right value for node

Looking at the calling code pasted...
The calling code does not allocate node; it's an uninitialized pointer, which means it points to a random location in memory.

Misread that code due to the naming.  The child passed down is an uninitialized pointer, but that won't case a segfault in the demonstrated code because it's never dereferenced.
The first time { is entered, it should work fine.  The second time it should segfault because this = node sets this to an uninitialized pointer.

A:

You are initializing your node pointers incorrectly. This means that the node variable you are passing around is invalid and points randomly into memory, almost certainly into memory that your process does not own, causing a segmentation fault. Try this instead:
// Change (1): new return type, parameter removed
struct vsm_node* vsm_initnode()
{
    struct vsm_node* node;
    node              = malloc(     sizeof(struct vsm_node)); // Change (2)

    // The following lines are unnecessary - change (3)
    //node->attrs       = malloc(36 * sizeof(struct vsm_attribute *));
    // node->children    = malloc( 8 * sizeof(struct vsm_node *));

    node->numchildren = 0;

    int i;
    for (i = 0; i < 36; ++i)
        node->attrs[i] = NULL; // unnecessary but good practice
    for (i = 0; i  < 8; ++i)
        node->children[i] = NULL;

    return node;
}

void vsm_addchild(struct vsm_node *node, struct vsm_node *child)
{
    node->children[node->numchildren] = child;
    ++(node->numchildren);
}

Explanations for each error:
(1) - You were initially passing struct vsm_node* as a parameter to the function. This allows you to modify whatever value that pointer refers to. However, while you can modify the pointer itself (as you were by a call to malloc), those changes are not reflected in the caller. All of your memory allocation and initialization was just wasted.
(2) - A pointer of type struct vsm_node* must point to memory large enough to hold a struct vsm_node. Instead, you previously were allocating enough memory to hold a struct vsm_node*, which is not nearly large enough. A good rule of thumb is that the right side of a malloc call should contain one less level of indirection than the left side. That is, if the variable you're assigning into has type T**, then the sizeof call inside of malloc should refer to type T*, and so on for any number of * characters.
(3) Your struct definition is as follows: 
struct vsm_node {
    int                   numchildren;
    struct vsm_attribute *attrs   [36];
    struct vsm_node      *children[8];
};

This means that when you allocate a struct vsm_node object, whether by using malloc or by simply declaring a variable of type struct vsm_node, it already has enough memory for both of your arrays of pointers. Allocating more memory is not only unnecessary but wasteful. It can also cause your program to behave differently than it would if you simply used the arrays with allocating additional memory.

