3

I've been struggling with this one for a few hours now and I'm at a loss as to what's happening. This is the code for program.c:

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

#define SPACE 32
#define INITIAL 4

typedef struct {
    char *town;
    char *country;
} town_t; 

typedef struct {
    int num_towns, current_size;
    town_t **towns_list;
} index_t;

int main(int argc, char *argv[]) {

    index_t town_index;
    town_index.current_size = INITIAL;
    town_index.towns_list = malloc(town_index.current_size * sizeof(*(town_index.towns_list)));
    assert(town_index.towns_list != NULL);

    printf("Step: %d\n", 1);
    town_index.towns_list[0]->town = malloc(4 * sizeof(*(town_index.towns_list[0]->town)));
    printf("Step: %d\n", 2);
    assert(town_index.towns_list[0]->town != NULL);

    return 0;
}

On Linux this is how it runs:

./program
Step: 1
Segmentation fault

but on Windows it prints out

program.exe
Step: 1
Step: 2

as I'd expect, which really isn't helping. For the Linux output, however, clearly the first print statement is being executed but not the second, which would lead me to think that the line between is that one at fault. Particularly, I think doing town_index.towns_list[0] is causing me issues, but I cannot say why.

This is a relatively complex data structure, so maybe I'm getting lost at some point. Basically town_index is meant to be a index struct that contains the current number of towns in towns_list and current_size which reflects the space currently available to save towns. It also contains an array of pointers to town_ts which contain the name and country as strings.

I've tried to use Valgrind, but it's really not helping out much. Here's a Pastebin for those who want to see.

This is a simplified scenario of what I was experiencing in another program, so don't any mind magic numbers and whatnot.

This is on VirtualBox Linux Mint 64-bit.


Unrelated question, if anyone can: How do I get Valgrind to display the precise lines? I see that everywhere else online, but my output just tells me the folder in which the program and function is, which isn't much help.

9
  • 1
    Welcome to Stack Overflow! It sounds like you may need to learn how to use a debugger to step through your code. With a good debugger, you can execute your program line by line and see where it is deviating from what you expect. This is an essential tool if you are going to do any programming. Further reading: How to debug small programs. Commented Oct 11, 2016 at 11:31
  • 1
    a friendly recommendation: do not use the suffix _t to indicate typenames, as they are reserved implicitly by the standard and explicitly by the POSIX standard. (hint) Commented Oct 11, 2016 at 11:35
  • 1
    @PaulR Thanks for advice! I can't believe it hadn't occurred to me that this would be a thing, I'll definitely look into it :) Commented Oct 11, 2016 at 12:07
  • 1
    @Arkantos just because others are not careful enough, it does not mean, that they are right :) I can only share you my conventions: I usually use CamelCasedNames for type names, (eg. typedef struct my_type { /* ... */ } MyType;) and mostly snaked_cased_names for variables and functions. (This convention does not ban the mixedCamelCasedNames to be used for function names, if that's what you prefer.) (Ofc my convention is way more complex than that, but for now, this should be enough for you to get the point :)) Commented Oct 11, 2016 at 12:19
  • 1
    @PeterVaro That's really helpful, thanks! I like the sound of that style! :) I'll try it out for future projects! Btw, do I not have enough rep to vote on comments? Cause I'd love to upvote yours but I can't, it seems :P Commented Oct 11, 2016 at 12:31

2 Answers 2

4

You initialized town_index.towns_list, but not town_index.towns_list[0], so town_index.towns_list[0]->town is undefined behaviour.

You missed something like

for (int i = 0; i < town_index.current_size; ++i)
    town_index.towns_list[i] = malloc(sizeof **town_index.towns_list);

for the second dimension.

Sign up to request clarification or add additional context in comments.

1 Comment

Ah fantastic, just what I needed, thanks a ton! This cleared it right up and also fixed the bigger program I was working on :)
0

town_index.towns_list and town_index.towns_list[0] are not the same. You initialize town_index.towns_list but town_index.towns_list[0] is equal to 0. The crash caused by dereferencing town_index.towns_list[0]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.