Thread: std::string.assign segfault

  1. #1
    Registered User
    Join Date
    May 2012
    Posts
    12

    std::string.assign segfault

    I use a std::string inside of a class I allocate dynamically, and I crash or get segfaults whenever I try to use the string. I assume I'm not initializing it right somehow, but I don't know what to do.

    Here is the class:
    Code:
    class cInterface
    {
        public:
            std::string Text;
            bool done;
            cInterface()
            {
                done=false;
            }
            ~cInterface()
            {
                Text.clear();
            }
    };
    cInterface* ckInterface;
    int numInterfaces;
    Here is the allocation of cInterface:
    Code:
    int newInterface()
    {
        int ID = -1;
        if(numInterfaces == 0)
        {
            ID = 0;
            ckInterface = (cInterface*)malloc(sizeof(cInterface) < 1 ? 1 : sizeof(cInterface));
            numInterfaces++;
        }
        else
        {
            for(int i=0; i<numInterfaces; i++)
            {
                if(ckInterface[i].done == true) { ID = i; break; }
            }
        }
        if(ID == -1)
        {
            ID = numInterfaces;
            ckInterface = (cInterface*)realloc(ckInterface, (numInterfaces+1)*sizeof(cInterface));
            numInterfaces++;
        }
        return ID;
    }
    Doing something like this causes me to crash:
    Code:
    int ID = newInterface();
    ckInterface[ID].Text.assign("Segfault happens here");
    What am I missing? I tried adding
    Code:
    Text = "";
    or
    Code:
    Text.resize(512);
    to the constructor of the class, but that didn't fix the issue :/

  2. #2
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by Alexander Edgar View Post
    Here is the allocation of cInterface:
    Code:
    int newInterface()
    {
        int ID = -1;
        if(numInterfaces == 0)
        {
            ID = 0;
            ckInterface = (cInterface*)malloc(sizeof(cInterface) < 1 ? 1 : sizeof(cInterface));
            numInterfaces++;
        }
        else
        {
            for(int i=0; i<numInterfaces; i++)
            {
                if(ckInterface[i].done == true) { ID = i; break; }
            }
        }
        if(ID == -1)
        {
            ID = numInterfaces;
            ckInterface = (cInterface*)realloc(ckInterface, (numInterfaces+1)*sizeof(cInterface));
            numInterfaces++;
        }
        return ID;
    }
    Red flags!
    Using C memory allocation in C++ is walking through a minefield as non-pod objects are not constructed.
    Here, std::string's allocators do not get the scope to reserve memory for the string.

    Read this thoroughly:
    [16] Freestore management Updated! , C++ FAQ

  3. #3
    Registered User
    Join Date
    May 2012
    Posts
    12
    So I switched to new and delete, but I didn't find a good replacement for realloc. Is there a way to do something similar without having to rewrite my entire program to use std::vector? I tried using this, which I thought would be ok because cInterface has no pointers in it:

    Code:
        if(ID == -1)
        {
            ID = numInterfaces;
            //ckInterface = (cInterface*)realloc(ckInterface, (numInterfaces+1)*sizeof(cInterface));
            cInterface* oldface = new cInterface[numInterfaces];
            oldface = ckInterface;
            delete [] ckInterface;
            ckInterface = new cInterface[numInterfaces+1];
            ckInterface = oldface;
            delete [] oldface;
            numInterfaces++;
        }
    But I still segfault the second time I try to make a new interface (the first one gets created successfully now, though).
    Last edited by Alexander Edgar; 05-12-2012 at 01:54 PM.

  4. #4
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by Alexander Edgar View Post
    But I still segfault the second time I try to make a new interface (the first one gets created successfully now, though).
    A simple and quick but not elegant solution is to use C style strings here.
    (or you could allocate the total amount of memory required from scratch, and copy over the original, finally freeing it)
    You can also experiment a bit with allocators..but that would be reinventing the wheel and the end result will (probably) be something not as good as a standard container.

    The else logic in your newInterface function looks a bit fishy to me, but I'm not sure about that.
    Last edited by manasij7479; 05-12-2012 at 02:08 PM.

  5. #5
    Registered User antred's Avatar
    Join Date
    Apr 2012
    Location
    Germany
    Posts
    257
    Your custom destructor for cInterface is also completely unnecessary. The default destructor would destroy the Text object anyway.

  6. #6
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    I've just about never seen a beginner on here use realloc correctly, and you weren't either I'm afraid. Hint, it's about handling failure correctly.Just switch to a vector, which will make it a whole lot simpler and more efficient.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  7. #7
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by Alexander Edgar
    So I switched to new and delete, but I didn't find a good replacement for realloc. Is there a way to do something similar without having to rewrite my entire program to use std::vector?
    Do something like this:
    Code:
    cInterface *newface = new cInterface[++numInterfaces]; // allocate new interfaces
    std::copy(ckInterfaces, ckInterfaces + numInterfaces - 1, newface); // place holder for whatever code will make deep copies
    //
    // ... whatever you intend to do with the new object @ckInterfaces[numInterfaces - 1]
    //
    delete [] ckInterfaces; // delete the old
    ckInterfaces = newface; // assign the new
    This is how it's usually moved to new memory when you reallocate.
    Last edited by whiteflags; 05-12-2012 at 02:25 PM.

  8. #8
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    This is how it's usually moved to new memory when you reallocate.
    You should really consider using `std::swap_ranges(???, ???, ???);'.

    If the class follows a compatible swap protocol it is usually a lot nicer.

    Soma

  9. #9
    Registered User
    Join Date
    May 2012
    Posts
    12
    Thanks whiteflags, that worked! Also, in regards to iMalc:
    I've just about never seen a beginner on here use realloc correctly, and you weren't either I'm afraid. Hint, it's about handling failure correctly.
    Would the right way to use realloc look something like this?

    Code:
    if(ID == -1)
    {
        ID = numInterfaces;
        cInterface* newface = (cInterface*)realloc(ckInterface (numInterfaces+1)*sizeof(cInterface));
        if(newface != NULL) { ckInterface = newface; }
        else { printf("Error allocating memory in newInterface(), but there is apparently nothing I can do about it so I don't know what the point of this is\n"); free(ckInterface); exit(1);  }
        numInterfaces++;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Unable to assign int to string. HELP!
    By cprogbiginner in forum C Programming
    Replies: 1
    Last Post: 04-29-2012, 07:28 AM
  2. String::assign problems
    By @nthony in forum C++ Programming
    Replies: 6
    Last Post: 11-06-2008, 09:31 AM
  3. assign value to string
    By rahulsk1947 in forum C Programming
    Replies: 3
    Last Post: 04-06-2006, 03:40 AM
  4. string.assign -- SEGFAULT problems
    By nateDC in forum C++ Programming
    Replies: 5
    Last Post: 01-20-2005, 03:03 PM
  5. Replies: 12
    Last Post: 10-14-2003, 10:17 AM

Tags for this Thread