Converting a std::list to char*[size]

前端 未结 6 1248
温柔的废话
温柔的废话 2021-01-21 20:54

for some reason I cannot explain, every single item in the character array...is equal to the last item added to it...for example progArgs[0] through progArgs[size] contains the

相关标签:
6条回答
  • 2021-01-21 21:11

    item has scope local to the loop. The propArgs array therefore contains a bunch of stack-based pointers, likely all the same. You can examine how this works in the debugger, just step thru the loop twice and it should be clear what's going on.

    By the time you exit the loop, the buffer addressed by the common pointer contains the most recently-copied c_str().

    You could fix this by doing

    char* item = new char[strlen((*t).c_str()) + 1];
    

    but then you'd have to delete[] all the propArgs array entries when you exit the loop.

    This code shows a fundamental lack of understanding of memory management such that further reading might be useful before restructuring the code. If the code used here was in only slightly more complex context than this example, it might just crash since any access of propArgs outside the loop would rely on an invalid (no longer in scope) item.

    0 讨论(0)
  • 2021-01-21 21:15

    You're setting progArgs[count] to the same item every time!

    int count = 0;
    char *progArgs[commandList.size()]
    
    for(list<string>::iterator t=commandList.begin(); t!=commandList.end(); t++)
    {
        char * item = new char[strlen((*t).c_str()) + 1]; //create new character string
        strcpy(item, (*t).c_str()); //convert from const char to char
        progArgs[count] = item;
        count++;
    }
    

    Then remember to call delete[] for each element in progArgs.

    Personally, I'd create an array of string and convert to char * on the fly as needed.

    0 讨论(0)
  • 2021-01-21 21:22

    You're assigning the same pointer (the address of the first element of the stack array item) to each element of progArgs, then repeatedly overwriting that memory. You can do:

    progArgs[count] = strdup(t->c_str());
    

    and get rid of the first two lines of the for body.

    strdup allocates memory, so you will have to free each element with free later. Also, you were not allocating a character for the NUL-terminator. You need would strlen + 1. However, this is not an issue with strdup, since it allocates for you.

    0 讨论(0)
  • 2021-01-21 21:24

    You're right:

    for(list<string>::iterator t=commandList.begin(); t!=commandList.end(); t++)
    {
        char item[strlen((*t).c_str())]; //create character string
    

    ...this does create an array, but it creates it on the stack, so when you reach the end of its scope, it gets destroyed.

        strcpy(item, (*t).c_str()); //convert from const char to char
        progArgs[count] = item;
        count++;
    }
    

    ...and this closing brace marks the end of its scope. That means you're creating a string, putting it into your array, then destroying it before you add the next one. Thanks to the fact that you're creating them all on the stack, each new one you create is being created in exactly the same place as the previous one, so it's no surprise that at the end of it all, you have a bunch of identical strings.

    Perhaps it would be better if you told us what you're trying to accomplish here, so we can help you do that.

    0 讨论(0)
  • 2021-01-21 21:30

    progArgs is an array of pointers to char.

    You set each of these pointers to point to item. item is a local variable in the loop, so as soon as the loop exits, item no longer exists and the pointers are no longer valid[*]. However, in your C++ implementation, they all still point to the bit of memory which used to be the array item on the stack. This memory contains whatever it was last used for, which is the sequence of characters from the last string in the list.

    If you want to copy a list of strings to an array, it would be better if possible to use an array of strings:

    std::string progArgs[commandList.size()] // if your compiler has C99 VLAs as an extension
    int count = 0;
    
    for(std::list<std::string>::iterator t=commandList.begin(); t != commandList.end(); ++t) {
        progArgs[count] = *t;
        ++count;
    }
    

    Or even better, use a vector instead of an array:

    std::vector<std::string> progArgs(commandList.begin(), commandList.end());
    

    [*] to be more precise, the scope of item is a single repeat of the loop, it's nominally "created" and "destroyed" each time around. But this doesn't do any work - on your C++ implementation the same region of memory is re-used each time, and there's no work needed to create or destroy an array of char on the stack.

    0 讨论(0)
  • 2021-01-21 21:33

    The char array item is local variable and is available only within the for loop.

    Instead allocate it dynamically.

    0 讨论(0)
提交回复
热议问题