Liandri
Liandri

Reputation: 313

Unknown Segfault

Thanks in advance for your help. I've done all the research I could trying to debug this. Adding printf's seems to change where the segfault occurs. I'm hardly familiar with gdb but somehow the program ran without issue in it. I've got some quantum observation problem going on. Let's get into the code.

This is just to reacquaint myself with C. The segfault is happening somewhere in create_string(). I could never get a printf() to show up right before the set_string(str, src); call.

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

typedef struct {
    char* value;
    size_t mlength;
    size_t length;
} StringContainer;

typedef struct {
    StringContainer* value;
    StringContainer* next;
} StringContainerList;


void set_string(StringContainer *str, const char* src);
StringContainer* create_string(const size_t max_length, const char* src);
size_t string_length(StringContainer* str);

int main(int argc, char *argv[])
{
    StringContainer* str = create_string(100, "The quick brown fox jumped over the lazy dog.");

    printf("Test: string_length\n");
    printf("%zu\n", string_length(str));
    return 0;
}

StringContainer* create_string(const size_t max_length, const char* src)
{
    StringContainer* str;
    size_t str_len;

    if ( src == NULL )
    {
        str_len = 0;
    }
    else
    {
        str_len = strlen(src);
    }

    str = (StringContainer*)malloc(sizeof(StringContainer));

    str->mlength = max_length;

    if ( str_len > 0 )
    {
        // set_string will delayed-malloc str->value :)
        set_string(str, src);
    }

    return str;
}

void set_string(StringContainer* str, const char* src)
{
    if (str->value == NULL)
    {
        str->value = (char*)malloc(str->mlength * sizeof(char));
        memset(str->value, '\0', str->mlength);
    }

    strcpy(str->value, src);

    str->length = strlen(str->value);
}

size_t string_length(StringContainer* str)
{
    char* value = str->value;
    size_t max_length = str->mlength;
    size_t offset_idx = 0;
    size_t division = max_length / 2;

    while (division != 0)
    {
        if ( value[offset_idx + division] != '\0' )
        {
            offset_idx = offset_idx + division;
        }

        division /= 2;
    }

    return offset_idx;
}

Thanks all for your time. I'm sure it's simple, something possibly fundamental, but my Google-foo is not developed enough to find the root of the issue.

Also, is this design pattern common? Obviously the malloc's should have free's associated. I'll also add in checking the malloc was successful.

Upvotes: 0

Views: 363

Answers (1)

Rohan
Rohan

Reputation: 53326

In the create_string() function you should properly set the values of malloced str so that it does not contain any random values.

Especially, str->value is not set to NULL. And then you are checking it in set_string() which may not succeed and you would strcpy() to unallocated memory causing undefined behavior.

So for minimum update your create_string() function as

str = (StringContainer*)malloc(sizeof(StringContainer));

str->mlength = max_length;
str->value = NULL; //add this

Upvotes: 2

Related Questions