Steve Berenbaum
Steve Berenbaum

Reputation: 43

Heap corruption detected in C++ after removing strings

When running this code I get an error as shown in the image below.

I've tried running it on GCC compiler and it worked fine. But when running it on Visual Studio on Windows this error appeared:

Debug Error!

Program: C:\Users\yudab\source\repos\Project2\Debug\Project2.exe

HEAP CORRUPTION DETECTED: after Normal block (#153) at 0x014FD2E0.

CRT detected that the application wrote to memory after end of heap buffer.

After some testing it seems as the error only appears after trying to delete the second word.

#include <cstring>
#include <string>
#pragma warning(disable : 4996)

#include <iostream>
using namespace std;

void delStr(char**& lexicon, int& lexSize, char word[]);
void printAll(char** lexicon, int lexSize);
void retract2dArr(char**& arr, int& size);

int main() {                    
    char** lexicon = new char* [3]; 
    lexicon[0] = new char[6]{ "hello" };
    lexicon[1] = new char[5]{ "test" };
    lexicon[2] = new char[6]{ "world" };
    int size = 3;
    char removeTest[5] = { "test" }; //The first word I want to remove from the list
    char removeWorld[6] = { "world" }; //The second word I want to remove from the list

    printAll(lexicon, size); //First prints the entire list

    delStr(lexicon, size, removeTest); //Removes the first word
    delStr(lexicon, size, removeWorld); //Removes the second word

    printAll(lexicon, size); //Prints the list after deleting the words



    return 0;
}

void delStr(char**& lexicon, int& lexSize, char word[]) {

    bool toDelete = false;
    for (int i = 0; i < lexSize; i++) {
        if (strcmp(lexicon[i], word) == 0) {
            toDelete = true;
            for (; i < lexSize - 1; i++) {
                strcpy(lexicon[i], lexicon[i + 1]);
            }
        }
    }

    if (toDelete == true) {
        delete[] lexicon[lexSize - 1];
        retract2dArr(lexicon, lexSize);
    }

    return;
}

void printAll(char** lexicon, int lexSize) {

    for (int i = 0; i < lexSize; i++) {
        cout << lexicon[i];
        if (i != lexSize - 1) {
            cout << " ";
        }
    }
    cout << endl;

    return;
}


void retract2dArr(char**& arr, int& size) {

    size--;

    char** newArr = new char* [size];
    for (int i = 0; i < size; i++) {
        *(newArr + i) = *(arr + i);

    }

    printAll(newArr, size);
    delete[] arr;
    arr = newArr;

    return;
}

Upvotes: 4

Views: 321

Answers (2)

As kiran Biradar pointed out, the strcpy is to blame here. Although instead of copying each word in the lexicon to the memory allocated for the previous word, it would probably be better to simply move the pointers back withing the lexicon array.

Try something like this for your delStr function:

void delStr(char**& lexicon, int& lexSize, char word[]) {
    for (int i = 0; i < lexSize; i++) {
        if (strcmp(lexicon[i], word) == 0) {
            delete[] lexicon[i];
            for (; i < lexSize - 1; i++) {
                lexicon[i] = lexicon[i + 1];
            }
            retract2dArr(lexicon, lexSize);
        }
    }
}

P.S. You didnt need to use a toDelete flag, you could call teh retract2dArr function within the first if.

Upvotes: 1

kiran Biradar
kiran Biradar

Reputation: 12732

You can't strcpy one string to another

    if (strcmp(lexicon[i], word) == 0) {
        toDelete = true;
        for (; i < lexSize - 1; i++) {
            strcpy(lexicon[i], lexicon[i + 1]);
        }
    }

As length will be different for each strings.

Example:

lexicon[0] = new char[6]{ "hello" };
lexicon[1] = new char[5]{ "test" };  // length is 4
lexicon[2] = new char[6]{ "world" }; // length is 5

3rd string won't fit in 2nd string, it causes out of bound access.

Upvotes: 2

Related Questions