Easy C++ Memory Allocation Question!

Hi, i know i should know this, but i really need to be sure of the answer.

I need to allocate a string array. I'm using no MFC, so there are no CArray or something like that.

For allocing memory im using  
    m_StringVar = new char[m_ArraySize][m_ElementSize];

Is it needed to alloc memory for each individual element of the array???

for releasing memory i'm using

delete[] m_StringVar; - Once again, is it needed to free up each element's memory????

Please help-me!!
LVL 2
PedroGAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

KangaRooCommented:
What do you mean, free each elements's memory? delete[]m_StringVar is sufficient.
  new char[m_ArraySize][m_ElementSize];
means create an array with m_ElementSize char[m_ArraySize] objects
0
PedroGAuthor Commented:
well i must be doing something wrong!!

1 - i've defined m_StringVar as char* * but wen i compiled an error fired saying it can convert to char ** so i've replaced the statment for
 
(char * *) new char[m_ArraySize][m_ElementSize];

Now one error still presists - It says "non-constant expression as array bound" What ??? i whant to allocate the mem, but i do not know in advance what would be the array bounds, or string size.

3 - I whant to allocate m_ArraySize elements of m_ElementSize. Is this the right way to do it??

Please !

0
KangaRooCommented:
I usually avoid these constructs (we've got vectors and strings nowadays). A typedef usually helps out:
  typedef char cstr[256];
  cstr* strarray = new cstr[12];
0
Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

KangaRooCommented:
The sizes must be const, otherwise you do need the full dynamic stuff:
char** array = new char*[nEl];
for(int i = 0; i< nEl; ++i)
  array[i] = new char[strLen];

And likewise for delete.
0
PedroGAuthor Commented:
well but my string can go from 1 to 4000 characters. So i need to dinamicaly alocate the memory. What am i doing wrong ?
0
cyberfrankCommented:
Hi!

Like KangaRoo said, there are other more elegant options! One of them  -- id You can use MFC is using StringArray with CString
or if u use STL, then i.e. vector with string. It's much more elegant and safer. You have to do much less of the dirty job :-)

CF
0
PedroGAuthor Commented:
As you sad i'm doing this

mSt = (char **) new char[10];
      
for (int x = 0; x<10; x++ )
  mSt[x] = new char[350];

strcpy(mSt[5], "TEST" );

for ( x = 0; x<10; x++ )
 delete[] mSt[x];

delete[] mSt;

The problem is the last line, because i get a GPF ???


If i delete the last line, program runs but crashes on exit!!

0
cyberfrankCommented:
>mSt = (char **) new char[10];

Hi!

mSt = (char**)new char*[10]

It's not the same !pointer is DWORD and not a byte!

CF
0
ToronadoCommented:
Hi PedroG,

KangaRoo's idea is correct. Only you forgot a pointer sign in the first line.

Should be :
 mSt = (char **) new char*[10];

You are allocating an array of char *.

Now it will work.

Regards,
 Toronado.
0
nietodCommented:
Kangaroo's code  is correct, although i don't like his expanation  

>> The sizes must be const, otherwise you do
>> need the full dynamic stuff:

operator new[] can allocate an array whose size is determined at run-time. But if the array is multi-dimensional, that is, if it is an array of arrays.  The size of those arrays must be fixed at compile time.  i.e.

int ArraySize;

cin >> ArraySize;

new char[ArraySize]; // Legal;
new char [ArraySize][10] // Legal;
new char [ArraySize] [ArraySize]; // ERROR.

To get arround this, you can allocate arrays that store pointers to other arrays.  These arrays that are pointed to can then be allocated to whatever size is needed using new [].

Toronado,

Is your answer different than kangaroo's?  I don't think so.  Answering with someone else's previously posted answer is the EE equivalent of plaugerism.

Furthermore the (char **) cast in your answer us unecessary and is dangerious.
0
PedroGAuthor Commented:
i don't know who to award the point, but it's no you for sure
0
nietodCommented:
The choice is yours, but it seems to me that kangaroo posted the right answer (and first).  Didn't that answer help you?
0
KangaRooCommented:
For the dynamic case there are two main ways of doing this, the C++ way and the C way.
The C++ way

  vector<string> the_array(nEl);
  the_array[3] = string("Hello");
Thats about it.

The C way
  char** the_array;
  the_array = new char*[nEl];
  for(int i = 0; i < nEl; ++i)
     the_array[i] = new char[strLen];

  char* acstr = "Hello";
  if(strlen(acstr) > strLen)
  {
    delete []the_array[idx];
    the_array[idx] = new char(strlen(acstr)+1);
  }
  strcpy(the_array[idx], acstr);

  for(int i = 0; i < nEl;++i)
    delete []the_array[i];

Make your choice ;)  
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
ToronadoCommented:
Hi PedroG and nietod,

Sorry, my mistake. My answer was meant to be a comment. I checked the wrong box. The anser is the same, I only corrected the proposed code.

Regards,
 Toronado.
0
KangaRooCommented:
>> mSt = (char **) new char[10];
You are casting a char* to a char**. Avoid these C-style casts, they should never be necesary (Btw, no need for them with malloc either)
If you need the (char**) cast to satisfy the compiler you've made a mistake somewhere.
0
nietodCommented:
The "C++ way" tends to be far easier, safer and shorter!  however, I do think it is good to understand the "C way"  Especially since the "C++ way" is really just classes that handle the ugly details of the "C way" for you.

Toronado, appology accepted, forgive me for reacting a little harsly, but I don't like to see that go on.
0
ToronadoCommented:
Hi nietod,

>>Toronado, appology accepted, forgive >>me for reacting a little harsly, but >>I don't like to see that go on.

It's ok :-)

Toronado.
0
PedroGAuthor Commented:
KangaRoo, i realy liked alot the C++ way, the problem is that i'm building the array to use with a Oracle Library(OCI), and it must be a standard C array. I've been checking the documentation, and founded no way of getting a pointer the the real array behind vector(if there is one). Is there anyway to do it ??
0
KangaRooCommented:
Not that I know, vector<> doesn't even have to use an array.
You could write your own array class that encapsulates all the 'nasty' details. Even a simple version that handles allocation and deallocation could be worthwhile.
0
PedroGAuthor Commented:
thats funny, because is that what i'm doing.
0
nietodCommented:
>> vector<> doesn't even have to use an array
I don't think that is true.  I believe you are guaranteed that the elements in the vector are stored contiguously in an array.  Thus to get a pointer to the array you just need to get a pointer to the first element, which is easy enough to do.

I'll have to look int that.
0
KangaRooCommented:
Mhh, not in the 'style' of STL container requirements. Most requirements are about iterator behaviour and complexities. Could find any mention that elements must be stored in a contiguous chunk of memory.

========================================================================
  23.2.4.1  vector constructors, copy, and             [lib.vector.cons]
       assignment
    The constructor template <class InputIterator>  vector(InputIterator
    first,   InputIterator   last)  makes  only  N  calls  to  the  copy

    constructor of T (where N is the distance between  first  and  last)
    and  no  reallocations  if  iterators first and last are of forward,
    bidirectional, or random access categories.   It  does  at  most  2N
    calls  to  the  copy constructor of T and logN reallocations if they
    are just input iterators, since it is impossible  to  determine  the
    distance between first and last and then do copying.
========================================================================

This makes a vector implementation ** possible **. Other implementations can do better in this respect, but may suffer in other area's like random access of elements.
0
nietodCommented:
I've been meaning to look into this still.  (Been busy or wasting time with...) But I think what I'm thinking about is the basic_string class.  I beleive that class guarantees that the elements are contiguous.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.