Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / Managed C++ / October 2005

Tip: Looking for answers? Try searching our database.

Noob question, how to malloc/free for char** ?

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Rob Schieber - 20 Oct 2005 17:39 GMT
Hey guys,

If I have a pointer to a *char, how do I allocate and free memory for it?

for example, if I had:

char*  pstring = "Hello\0";
char** strings = &pstring;
strings[0] = pstring;

1.  Is this a valid way to set up a list of strings?
and
2.  How do I malloc/free the strings variable?  Or is it even necessary
since I'm initializing the pointer array to the address of the first string?

Thanks in Advance
Signature

Rob Schieber

Tom Serface - 20 Oct 2005 17:59 GMT
If I were you I'd use a vector to store the strings or if you are using MFC
you can use CStringList or CStringArray and use CStrings.  If you want to do
your own dynamic memory allocation I'd use 'new' and 'delete' instead of
malloc/free:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/exp
ress_25.asp

http://www.devx.com/tips/Tip/29166
http://www.cplusplus.com/doc/tutorial/tut3-4.html

Tom

> Hey guys,
>
[quoted text clipped - 13 lines]
>
> Thanks in Advance
Rob Schieber - 20 Oct 2005 18:15 GMT
> If I were you I'd use a vector to store the strings or if you are using MFC
> you can use CStringList or CStringArray and use CStrings.  If you want to do
> your own dynamic memory allocation I'd use 'new' and 'delete' instead of
> malloc/free:

Thanks Tom,

I wish I could use a vector, but the problem is that I need to set the
value of a struct which is of type char** .  I guess the more general
question is how do you allocate/free pointer to pointer values.

Signature

Rob Schieber

Tamas Demjen - 20 Oct 2005 19:34 GMT
> I wish I could use a vector, but the problem is that I need to set the
> value of a struct which is of type char** .  I guess the more general
> question is how do you allocate/free pointer to pointer values.

Even then I'd use std::string and pass .c_str() to the C call:

vector<string> strings;
strings.push_back("One");
strings.push_back("Two");
strings.push_back("Three");
// Now convert it into C-style:
vector<const char*> c_strings;
for(vector<string>::const_iterator it = strings.begin();
  it != strings.end(); ++it)
{
   c_strings.push_back(it->c_str());
}
CallThatOldCFunction(&c_strings[0]);

This way you're safe and don't have to allocate or free anything. It's
clear, exception safe, and as bug-free as possible (you have no control
over what the C call is doing).

You can replace vector with deque if you prefer.

If your C call is so badly designed that it doesn't support const
pointers, you need to use a trick in the for loop: Instead of s.c_str(),
which requires const-correctness, use &s[0], like this:

// Now convert it into C-style:
vector<char*> c_strings;
for(vector<string>::const_iterator it = strings.begin();
  it != strings.end(); ++it)
{
   c_strings.push_back(&(*it)[0]);
}
CallThatOldCFunction(&c_strings[0]);

Tom
Rob Schieber - 20 Oct 2005 20:08 GMT
>> I wish I could use a vector, but the problem is that I need to set the
>> value of a struct which is of type char** .  I guess the more general
[quoted text clipped - 35 lines]
>
> Tom

Thanks again for the help, I will try both suggestions, hopefully I can
get it to work :P

Signature

Rob Schieber

William DePalo [MVP VC++] - 20 Oct 2005 18:47 GMT
> Hey guys,
>
[quoted text clipped - 7 lines]
>
> 1.  Is this a valid way to set up a list of strings?

Well, if you can not use a standard container, then the first question you
need to ask yourself is whether your strings have a fixed maximum size. If
they do then the next question to ask is whether you can afford creating a
maximally sized array. If the answer to both questions is yes then you can
compute the product of the number of elements and their size (don't forget
the terminator) and then malloc the whole lot in one go.

The first string starts at offset 0, the second at offset n, the third at
offset 2n where n = the size of the buffer holding each string (not the
string length, btw).

If the answer to either question is false, then it seems to me that you
would be better off first allocating an array of pointers (LPCSTR or LPSTRs
as appropriate). Then you allocate each string as you would normally and set
the corresponding element in the array of pointers to the first byte of each
dynamically allocated string.

Regards,
Will
Rob Schieber - 20 Oct 2005 19:50 GMT
>>Hey guys,
>>
[quoted text clipped - 27 lines]
> Regards,
> Will

Thanks for the reply Will,

So I guess if I knew my list was going to be 2 items in length, and each
item was a maximum of 50 chars, I would want to do something like this?:

char* pstring1 = "pstring1\0";
char* pstring2 = "pstring2\0";

char** strings = malloc(2 * 50);
strings[0] = string1;
strings[50] = string2;

free(strings);
Signature

Rob Schieber

Tamas Demjen - 20 Oct 2005 20:57 GMT
> char* pstring1 = "pstring1\0";
> char* pstring2 = "pstring2\0";
[quoted text clipped - 4 lines]
>
> free(strings);

No.

char** strings = static_cast<char**>(malloc(2 * sizeof(char*));
strings[0] = string1;
strings[1] = string2;
free(strings);

Remember, strings stores char* pointers, not chars.

Tom
William DePalo [MVP VC++] - 21 Oct 2005 04:21 GMT
> Thanks for the reply Will,

You are welcome.

> So I guess if I knew my list was going to be 2 items in length, and each
> item was a maximum of 50 chars, I would want to do something like this?:
[quoted text clipped - 7 lines]
>
> free(strings);

Well, no. :)

The first two lines are OK. You are declaring two pointers to strings and
setting each to point to fixed strings which the compiler stores in the data
segment. So far, so good.

The next few lines exhibit some confusion.

On the left side of this declaration

> char** strings = malloc(2 * 50);

you have a pointer to a pointer to a character. Then you allocate 100 bytes
for it. Ut oh.

Since the variable strings holds a pointer to a pointer, strings[n] holds a
pointer, so these lines

> strings[0] = string1;
> strings[50] = string2;

are copying _pointers_ even though I _think_ that you intended for them to
copy _strings_.

To the end of this post I have appended tired old C source (definitely not
modern C++) that demonstrates handling an array of strings in three ways. In
the first I statically allocate the array. In the second I dynamically
allocate an array of fixed size strings. In the third I allocate an array of
variably sized strings.

In all cases, the size of the array is known at compile time. It gets even
uglier if the upper bound for the array is not known until runtime.

Note that I AM NOT advocating that you proceed down this path. I'd no sooner
suggest that than I'd suggest using an antique operating system whose name
ends in X. <gd&r> But you asked.

Finally note that buffer overruns are all to easy where null-terminated
strings are concerned. And exploiting this vulnerability is a favorite
technique of virus writers. If you must use this old stuff you may want to
read up on the safer variants of the old string functions here:

http://msdn2.microsoft.com/en-us/library/td1esda9

Regards,
Will

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>

#define SIZE  50
#define COUNT 10

int main()
{
unsigned int i, j;

// static allocation

{
 char strings1[COUNT][SIZE + 1] = { "zero", "one", "two", "three", "four",
                                  "five", "six", "seven", "eight",
"nine" };
 printf("\nStatic Allocation\n\n");

 for ( i = 0; i < COUNT; i++ )
 {
  printf( "String #%d is '%s', characters are ", i, strings1[i] );

  for ( j = 0; j < strlen( strings1[i] ); j++ )
   printf("'%c' ", strings1[i][j] );

  printf("\n\n");
 }
}

// dynamic allocation of fixed-size strings

{
 char (*strings2)[COUNT][SIZE + 1];

 printf("\nDynamic Allocation - Fixed Size\n\n");

 strings2 = calloc(COUNT, SIZE + 1);

 strcpy( (*strings2)[0], "zero");
 strcpy( (*strings2)[1], "one");
 strcpy( (*strings2)[2], "two");
 strcpy( (*strings2)[3], "three");
 strcpy( (*strings2)[4], "four");
 strcpy( (*strings2)[5], "five");
 strcpy( (*strings2)[6], "six");
 strcpy( (*strings2)[7], "seven");
 strcpy( (*strings2)[8], "eight");
 strcpy( (*strings2)[9], "nine");

 for ( i = 0; i < COUNT; i++ )
 {
  printf( "String #%d is '%s', characters are ", i, (*strings2)[i] );

  for ( j = 0; j < strlen( (*strings2)[i] ); j++ )
   printf("'%c' ", (*strings2)[i][j] );

  printf("\n\n");
 }
}

// dynamic allocation of fixed sized strings

{
 char *strings3[COUNT];

 printf("\nDynamic Allocation - Variable Size\n\n");

 strings3[0] = malloc(strlen("zero") + 1);
 strcpy(strings3[0], "zero");

 strings3[1] = malloc(strlen("one") + 1);
 strcpy(strings3[1], "one");

 strings3[2] = malloc(strlen("two") + 1);
 strcpy(strings3[2], "two");

 strings3[3] = malloc(strlen("three") + 1);
 strcpy(strings3[3], "three");

 strings3[4] = malloc(strlen("four") + 1);
 strcpy(strings3[4], "four");

 strings3[5] = malloc(strlen("five") + 1);
 strcpy(strings3[5], "five");

 strings3[6] = malloc(strlen("six") + 1);
 strcpy(strings3[6], "six");

 strings3[7] = malloc(strlen("seven") + 1);
 strcpy(strings3[7], "seven");

 strings3[8] = malloc(strlen("eight") + 1);
 strcpy(strings3[8], "eight");

 strings3[9] = malloc(strlen("nine") + 1);
 strcpy(strings3[9], "nine");

 for ( i = 0; i < COUNT; i++ )
 {
  printf( "String #%d is '%s', characters are ", i, strings3[i] );

  for ( j = 0; j < strlen( strings3[i] ); j++ )
   printf("'%c' ", strings3[i][j] );

  printf("\n\n");
 }
}

return 0;
}

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.