Thread: Unexplainable Segvault in Constructor Method

  1. #1
    Registered User
    Join Date
    Nov 2014
    Posts
    9

    Question Unexplainable Segvault in Constructor Method

    Hey all out there!
    I am a kind of new to C coming from Python and Bash
    (if bash is a real programming language ) and have a header file to work on String arrays/lists with big size. It's working pretty fine, excepted that my constructor is'nt working. Somtimes it returns
    a structure and somtime not.
    If it returns no structure I get a segfault and the programs is killed by the Kernel.
    I also asked some friends, but they also don't know what the problem is.
    In the file in the Appendix are only the relevant parts.
    By the way:
    1. I am using gcc 4.8.x
    2. On Ubuntu GNU/Linux 14.04 x86_64
    3. I tried also on Arch (GNU) Linux, but it didn't work, too

    Code:
        #include<stdlib.h>
    #include<string.h>
    #include<stdio.h>
    
    /*
       the code is documentation enough
     */
    
    
    void exitMemoryError(void)
    {
        printf("\n\n\n\tWARN: ERROR: OUT OF MEMORY!\n\n\n");
        exit(-105);
    }
    
    /* contains a string, kind of data element */
    struct String
    {
        char *value;
        unsigned int len;
    };
    
    
    
    struct String * newString(char * str)
    {
        struct String * string=malloc(sizeof(struct String));
        if(! string)
        {
            exitMemoryError();
        }
        string->value=str;
        string->len=strlen(str);
        return string;
    }
    Attached Files Attached Files
    Last edited by LittleByBlue; 11-11-2014 at 10:08 AM. Reason: improved

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Post the smallest and simplest compilable program that demonstrates your problem. You should post code within [code][/code] bbcode tags.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    The problem is that you allocated space for the struct, but not the data you want the struct to store. You need to use malloc again and assign to the value field. You shouldn't just set value equal to the incoming pointer, because that pointer may not remain valid. You need to copy the incoming string into memory that you've allocated.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Ah, I see that you updated your post. That's good.

    Look at struct String: you have a pointer member that presumably will point to the first character of a null terminated string. No problem there. Now look at your newString function: you allocate space for a struct String object, but you did not allocate any space for the string that it should store. Then, you assign str to string->value. This is not necessarily a Bad Thing, but it probably is. To know what went wrong, we need to see the code that calls newString, which is why I told you to post the smallest and simplest compilable program that demonstrates your problem.

    By the way, the .h hints that this is a header file, and if so, it should have inclusion guards. Furthermore, you should not be defining functions in the header file, but rather forward declare them and define them in a source file.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Quote Originally Posted by Elkvis View Post
    The problem is that you allocated space for the struct, but not the data you want the struct to store. You need to use malloc again and assign to the value field. You shouldn't just set value equal to the incoming pointer, because that pointer may not remain valid. You need to copy the incoming string into memory that you've allocated.
    And that would explain why the code sometimes works and doesn't, because the data at that address would be changed beyond the control of the structure. It makes good sense to allocate a private copy.

  6. #6
    Registered User
    Join Date
    Nov 2014
    Posts
    9
    I changed, as You told me the the constructor to
    Code:
    struct String * newString(char * str)
    {
        struct String * string=malloc(sizeof(struct String));
        if(! string)
        {
            exitMemoryError();
        }
        string->value=malloc(sizeof(char)*strlen(str));
        string->value=str;
        string->len=strlen(str);
    
        return string;
    }
    This was the Error. Thanks a lot!!

    The original "project" is a bit longer and seperated in different files. For making it easier
    I copyed all together in one .h file.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Err... you still have a problem: you allocated memory for the string wrongly, and then you overwrote the pointer to the memory allocated, resulting in a memory leak. Rather, you need a +1 when allocating memory to account for the null character, then you need to use say, strcpy to copy over the string. Since you will be calling strlen for string->len, you might as well assign to string->len first then use string->len in the malloc call.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Shouldn't it be :
    Code:
    *(string->value) = *str;
    ?

    Or am I thinking about this wrong?

    My bad, I was right in concept but then I saw Laser's post about strcpy. Good.

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by MutantJohn
    Or am I thinking about this wrong?
    That would only copy the first character of the string.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    Registered User
    Join Date
    Nov 2014
    Posts
    9
    Quote Originally Posted by MutantJohn View Post
    Shouldn't it be :
    Code:
    *(string->value) = *str;
    ?
    no, my code is right(I tested it).
    Last edited by LittleByBlue; 11-11-2014 at 12:01 PM.

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by LittleByBlue
    no, my code is right(I tested it).
    No, the code that you posted in post #6 is wrong. As I mentioned in post #7, it results in a memory leak which probably does not show up in your testing. Furthermore, it should exhibit the same problem as your code in post #1. If it does not, then it is merely by chance.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    Registered User
    Join Date
    Nov 2014
    Posts
    9
    @laserlight:
    Would be
    Code:
    ...
    string->value=malloc(sizeof(char)*(strlen(str)+1));
    strcpy(string->value,str);
    better?

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    That would be correct. However, I suggest:
    Code:
    string->len = strlen(str);
    string->value = malloc(string->len + 1);
    strcpy(string->value, str);
    sizeof(char) == 1 will always be true, so there is no need to multiply by that. If you really want to, then write:
    Code:
    string->value = malloc(sizeof(string->value[0]) * (string->len + 1));
    Also, since you check the result of malloc when allocating for string, you might as well check it when allocating for string->value.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Registered User
    Join Date
    Nov 2014
    Posts
    9
    Ok thanks. Final solution is
    Code:
    struct String * newString(char * str)
    {
            struct String * string=malloc(sizeof(struct String));
            if(! string)
            {
                    exitMemoryError();
            }
    
            string->len=strlen(str);
            string->value=malloc(sizeof(str[0])*((string->len)+1));
            if(!string->value)
            {
                    exitMemoryError();
            }
            strcpy(string->value,str);
            return string;
    }
    Last edited by LittleByBlue; 11-11-2014 at 12:21 PM.

  15. #15
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    There is no point calling strlen(str) twice when the string that str points to does not change, hence my suggestion to assign to string->len first. By assigning to string->len again in the malloc call, you merely make your code unnecessarily complicated and possibly less efficient. In fact, string->len is probably now wrong, because it includes the null character when it conventionally should not.

    Next, this is wrong:
    Code:
    free(str);
    By doing this, you make it unnecessarily illegal to call newString("hello") or newString(x) where x is an array of char that stores a string. Even if malloc was used, it could well be that the caller wants to use the string, not have it deallocated unexpectedly.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How do I call a method without it's constructor first?
    By JazzEngineer in forum C# Programming
    Replies: 5
    Last Post: 09-07-2013, 01:28 AM
  2. Unexplainable behavior...
    By wpcarro in forum C Programming
    Replies: 6
    Last Post: 01-06-2011, 06:15 PM
  3. Using my own method in a constructor...
    By AngryStyro in forum C++ Programming
    Replies: 13
    Last Post: 06-04-2008, 01:02 PM
  4. Windows Service class constructor and OnStart method
    By George2 in forum C# Programming
    Replies: 0
    Last Post: 04-14-2008, 07:18 AM
  5. yet another unexplainable flaw
    By stormbreaker in forum C++ Programming
    Replies: 4
    Last Post: 06-01-2003, 12:56 PM

Tags for this Thread