Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Delete array of c-strings/other type of array

[EDIT]

Okay, so that makes sense, thank you sharptooth and CashCow. You can't delete data allocated as const, which makes string literals out of the question. So if I change my initialization to look like this:

char **groups = new char*[2];

char *s1 = new char[10];
char *s2 = new char[10];
char c1 = 'a';
char c2 = 'b';
for(int i = 0; i < 9; i++)
{
    s1[i] = c1;
    s2[i] = c2;
}
s1[9] = NULL;
s2[9] = NULL;

groups[0] = s1;
groups[1] = s2;

Hard code my for loop so that it will only iterate through i=1 and i=2, then everything works.

I noticed that the int arraySize = sizeof arr / sizeof *arr; only seems to work when the array is allocated with new[] instead of locally. This is because my original char ** groups; variable decays to a pointer, right?

Now I'm wondering, is there anyway to tell whether or not data is const?


[ORIGINAL]

I know that arrays and pointers are evil, and that there are these great things called vectors and linked lists.

But, I'm a newbie when it comes to memory management, and I'm feeling a little masochistic. Say I make an array of C-strings. I know from this question and the FAQ-Lite that you must match type a = new type[len]; with delete[] a;. Or so I think.

FAQ-Lite talks about managing jagged arrays here, but he's focusing on matrices, and I'm not certain if it applies to what I'm doing.

This code makes sense to me, but fails an assertion (debugging on Visual Studio 2008) on delete[] a;. What is wrong with this, and how do I accomplish this task?

#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    // Initialize array of C-strings
    char *groups[] = {"testing1", "testing2"};

    // Sanity check
    cout << groups[0] << endl;
    cout << groups[1] << endl;

    // Compute size
    int arrsize = sizeof groups / sizeof groups[0];
    cout << arrsize << endl;

    for (int i = 0; i < arrsize; i++)
    {
        // Since each string is a char array, free string memory with delete[]
        cout << "Deleting element #" << i << endl;
        delete[] groups[i];
    }
    cout << "Freeing pointer array." << endl;

    // Free the memory storing the pointers
    delete[] groups;

    return 0;
}
like image 905
michael.bartnett Avatar asked Dec 28 '22 04:12

michael.bartnett


2 Answers

You try to deallocate string literals - that's undefined behavior:

char *groups[] = {"testing1", "testing2"};
delete[] groups[i];

only call delete[] on pointers returned by new[].

like image 177
sharptooth Avatar answered Dec 30 '22 16:12

sharptooth


Literal strings are expressions like "testing1". They are of type const char *. They cannot be modified and they cannot be deleted. The actual text usually sits in the static read-only memory area of the program.

You can construct a char array that is writable like this:

char group[] = "testing1";

That is modifiable but you cannot delete it, nor can you extend it to make it bigger. It also has local scope so you cannot return it from a function.

like image 38
CashCow Avatar answered Dec 30 '22 18:12

CashCow