jswenson91
jswenson91

Reputation: 21

Error when deleting a pointer that has been declared as new?

I am writing a program right now that alters a C_String using pointers to the string. I have an implementation that works fine. The only problem I am running into is that when I reach the end of my program, if I try to delete the pointers I get an error.

My code:

void CStringSwitcher()
{

    string input = "";
    char* cStringArray = new char[ASIZE];
    char* reversed = new char[ASIZE];
    const char* originalReversed = reversed;
    char* pointers[POINTER_SIZE];
    memset(reversed, '\0', ASIZE);
    memset(cStringArray, '\0', ASIZE);
    memset(pointers, '\0', POINTER_SIZE);
    char* current = cStringArray;
    cout << "Enter a sentence on each line. Input a 0 to stop." << endl;

    // Receives input from the user and stores it into cStringArray
    int i = 0;
    do
    {
        cout << ">";
        cin.clear();
        fflush(stdin);
        input = "";
        getline(cin, input);
        if (input == "0")
            break;
        else
        {
            input.append("\n");
            pointers[i] = current;
            _CRT_SECURE_STRCPY(pointers[i], ASIZE - 1, input.c_str());
            current += input.length();
            i++;
        }
    } while(i < POINTER_SIZE);
    char* end = current;

    --i;
    do
    {
        /// Check if done
        if(i < 0)
            break;
        /// Copy from current to end
        current = pointers[i];
        do
        {

            *reversed++ = *current++;
        }while(current < end);
        /// Update end
        end = pointers[i];
        /// Update i
        --i;
    }while(true);
    *reversed = '\0';
    cout << endl << originalReversed << endl;
    system("PAUSE");
    //delete[] originalReversed;
    //delete[] cStringArray;
    return;
}

As it is written above the code works fine, however if I uncomment the two delete lines just before the return I was getting an error:

Project_06.exe has initiated a breakpoint

and the program crashes. Weird thing is I just ran the program again to get the exact wording of the error message and it runs with no error? Any ideas on why that is?

Upvotes: 1

Views: 122

Answers (2)

kfsone
kfsone

Reputation: 24249

I'm guessing that this code is an educational/practice piece to try and solidify your knowledge of pointers, but to be frank with you: it's an absolute horror to read.

This answer is in the spirit of "teach a man to fish".

Start by removing all of the allocations and instead use fixed-sized arrays.

char cStringArray[ASIZE] = "";
char reversed[ASIZE] = "";

This eliminates the need for the memsets for now, this assignment actually sets the entire array to 0s (see http://ideone.com/WmLtQp).

Doing it this way makes it much easier to catch corruption while running it thru the debugger.

Then switch the arrays over to dynamic allocations.

Lastly, don't mix stdin and cin, doing so can invoke undefined behavior.

---- Edit ----

Here is a C++-refactoring of your code. This particular piece shows both how to do it by hand (manually copying the bytes) and using C++ features to reduce the amount of work we have to do ourselves.

ideone live demo: http://ideone.com/0KuGiB

#include <iostream>
#include <string>
#include <vector>

void CStringSwitcher()
{
    std::vector<std::string> inputs;
    size_t totalLength = 0;

    std::cout << "Enter a sentence on each line. Input a 0 to stop." << std::endl;
    inputs.reserve(16);

    for ( ; /* until break */ ; ) {
        std::cout << ">";
        std::string input;
        getline(std::cin, input);
        if (input == "0")
            break;
        inputs.push_back(input);
        totalLength += input.length() + 1; // for the '\n'
    }

    std::string reversed = "";
    reversed.reserve(totalLength); // eliminate allocations

    // walk backwards thru the list of strings.
    for (auto inputsIt = inputs.rbegin(); inputsIt != inputs.rend(); ++inputsIt) {
        const std::string& input = *(inputsIt);

#ifndef REAL_CODE
        // educational, Do-It-Yourself way
        const size_t length = input.length();

        // walk backwards thru the characters
        for (size_t i = 0; i < length; ++i) {
            reversed += input[length - 1 - i];
        }
#else
        // call append with reversed iterators to do it for us.
        reversed.append(input.rbegin(), input.rend());
#endif

        // add the trailing '\n'
        reversed += '\n';
    }

    std::cout << std::endl << reversed << std::endl;

    // don't pause, set a break point at the end of the function
    // or run without debugging.

    return;
}

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

    return 0;
}

Upvotes: 1

Brainheav
Brainheav

Reputation: 1

_CRT_SECURE_STRCPY(pointers[i], ASIZE - 1, input.c_str());
current += input.length();

ASIZE-=input.length();

ASIZE-=input.length();

Don't know why it helps to get rid of error. This should only prevent from overflow if size of new string > size of the remaining bytes. Looks like some Microsoft-Specific magic.

Also there are many errors in you code, but this is another story. Just consider using vector, unique_ptr.

---EDIT---

I came with some weird things.

_CRT_SECURE_STRCPY is define to strcpy_s

#include <iostream>
#include <numeric>

using namespace std;

int main()
{
    char arr[10];
    iota(arr, end(arr), 'A');
    for (auto i : arr) cout << i << '\t'; cout << '\n';

    strcpy_s(arr, "");

    for (auto i : arr) cout << i << '\t'; cout << '\n';
}

My output is:

A B C D E F G H I J

(nonpritable characters)

It means that strcpy_s rewrites WHOLE destination buffer. Even if you pass one char.

Upvotes: 0

Related Questions