Board index » cppbuilder » Crash...

Crash...


2006-07-23 09:20:37 PM
cppbuilder8
Hi everyone,
Isn't it possible to create an array dynamically in C++ ? Here is a program
that compiles fine, but crashes at run time :
#include <iostream.h>
enum TYPE {INT, STRING, COLOR};
struct Command
{
char * m_name;
TYPE m_params[];
int m_paramsCount;
};
Command commands[] =
{
{"Flicker", {COLOR}, 1},
{"Play", {STRING}, 1},
{"Talk", {STRING, INT}, 2}
};
void main()
{
int max = 3;
for (int i = 0; i < max; i++)
{
Command c = commands[i];
cout << c.m_name << endl;
}
}
The first name "Flicker" is written and afterwards it crashes. Could someone
explain me what's happening ?
Thanks in advance,
Mark
 
 

Re:Crash...

Look at this:
Quote
struct Command
{
char * m_name;
TYPE m_params[];
int m_paramsCount;
};
and now this:
Quote
Command commands[] =
{
{"Flicker", {COLOR}, 1},
{"Play", {STRING}, 1},
{"Talk", {STRING, INT}, 2}
};
Not only is the dimension of Command::m_params not given, in the 'commands'
array it is initialized with two different sizes.
A declared array has the same size for each element. In the code shown the
third element, commands[2], is larger than the other two. That guarantees
problems. Re-think what you are doing and how you might implement it.
. Ed
Quote
Mark Morrisson wrote in message
news:44c37860$ XXXX@XXXXX.COM ...

Isn't it possible to create an array dynamically in C++ ? Here is
a program that compiles fine, but crashes at run time :

#include <iostream.h>

enum TYPE {INT, STRING, COLOR};

struct Command
{
char * m_name;
TYPE m_params[];
int m_paramsCount;
};

Command commands[] =
{
{"Flicker", {COLOR}, 1},
{"Play", {STRING}, 1},
{"Talk", {STRING, INT}, 2}
};

void main()
{
int max = 3;

for (int i = 0; i < max; i++)
{
Command c = commands[i];

cout << c.m_name << endl;
}
}

The first name "Flicker" is written and afterwards it crashes.
Could someone explain me what's happening ?
 

Re:Crash...

Hi Ed,
Thanks for your reply. I still need some precisions.
For me, the line :
TYPE m_params[];
declares a POINTER to an array of TYPE elements. So, its size is only the
size of a pointer.
When I declare thise Command element :
Command commands[] =
{
{"Talk", {STRING, INT}, 2}
};
it means that I allocate an array of 2 TYPE elements in the Command
structure, but the "size" of m_params is only equal to the size of a
pointer, isn't it ? Let's suppose the "size" of the structure comprises the
size of the allocated array as you said. So, it should be the same with
strings. Then, size of the first element = size of the "Talk" string + size
of 2 TYPE elements + sizeof(int). Hence, ALL elements of the commands[]
array have different sizes...
Could you explain me what the compiler does while executing this code ?
Thanks in advance,
Mark
 

{smallsort}

Re:Crash...

Quote
TYPE m_params[];

declares a POINTER to an array of TYPE elements. So, its size
is only the size of a pointer.
An array uses square brackets. A pointer uses an asterisk.
The statement
TYPE *m_params;
declares a pointer which can hold the address of a TYPE element. This may
be the first item of an array, the address of a single item or may even be
not initialized so not containing valid address.
Quote
Could you explain me what the compiler does while executing
this code ?
No I cannot. I do not know if your program is for DOS, 16 bit Windows, 32
bit Windows and if one of the first two, what memory model was used. Other
options settings may also alter how and what it does. You should look at it
yourself.
Open the CPU window while stepping through the code in the de{*word*81} and
watch what it does.
. Ed
Quote
Mark Morrisson wrote in message
news: XXXX@XXXXX.COM ...

Thanks for your reply. I still need some precisions.

For me, the line :

TYPE m_params[];

declares a POINTER to an array of TYPE elements. So, its size is only the
size of a pointer.

When I declare thise Command element :

Command commands[] =
{
{"Talk", {STRING, INT}, 2}
};

it means that I allocate an array of 2 TYPE elements in the Command
structure, but the "size" of m_params is only equal to the size of a
pointer, isn't it ? Let's suppose the "size" of the structure comprises
the
size of the allocated array as you said. So, it should be the same with
strings. Then, size of the first element = size of the "Talk" string +
size
of 2 TYPE elements + sizeof(int). Hence, ALL elements of the commands[]
array have different sizes...

Could you explain me what the compiler does while executing this code ?
 

Re:Crash...

Ed,
The debugguer just catches a memory fault exception.
If the statement
int a[];
isn't a pointer to an array, what is it ?
Please, I'd like to understand something. What is the fundamental difference
between :
struct Command { char * m_string; };
Command commands[] = { {"Flicker"} };
and
struct Command { int m_array[]; };
Command commands[] = { { {5, 6} } };
?
For me, an array of ints is just like a array of chars (= string), I don't
understand why the compiler should behave differently. What's wrong in the
2nd form ? It's precisely what I'd like to understand.
My program is just in Win32 console mode for 32-bit memory model. Well, it's
a classic program. But I don't see what would be different from a 16-bit
program for DOS concerning the question I have asked.
Regards,
Mark
 

Re:Crash...

Mark Morrisson wrote:
Quote
If the statement
int a[];
isn't a pointer to an array, what is it ?
It is an array of 0 elements. And it's sizeof() would be 0.
Quote
Please, I'd like to understand something. What is the fundamental difference
between :

struct Command { char * m_string; };
A structure containing pointers to char arrays, stored elsewhere.
It's sizeof() would be 4.
Quote
Command commands[] = { {"Flicker"} };
An array of structures (one structure). An actual block of memory
containing a pointer to the string "Flicker", stored in another part
of the program. sizeof(commands) is 4.
Quote
struct Command { int m_array[]; };
A structure that contains an int array of unspecified size.
It's sizeof() is unknown at this time.
Quote
Command commands[] = { { {5, 6} } };
An array of structures (again with only one element). An actual block
of memory containing an array of ints. It's sizeof() is 8.
Now, apply the above to what you thought you were doing, and you get
struct Command { int *m_array };
Command commands[] = { { {5, 6} } };
A structue containing one pointer to an array of int.
It's sizeof() is 4.
The array is stored elsewhere in the program.
Quote
For me, an array of ints is just like a array of chars (= string),
It is.
Quote
I don't understand why the compiler should behave differently.
It doesn't.
Quote
What's wrong in the 2nd form ? It's precisely what I'd like to understand.
[ ] is not a pointer. It is an array.
Quote
My program is just in Win32 console mode for 32-bit memory model. Well, it's
a classic program. But I don't see what would be different from a 16-bit
program for DOS concerning the question I have asked.
sizeof() would be different depending upon those many factors.
 

Re:Crash...

Hi Bob,
Thanks for your reply. Well, if I replace
TYPE m_params[];
with
TYPE * m_params;
then the program does not compile anymore. I get the following error :
Cannot convert 'int' to 'TYPE *'
at this line :
{"Flicker", {COLOR}, 1},
So, how could I write the program ? Of course, I always have the possibility
to affect the m_params parameter dynamically with new [], but I wanted to do
it statically.
Regards,
Mark
 

Re:Crash...

Quote
If the statement

int a[];

isn't a pointer to an array, what is it ?
int *xyz;
'xyz' is the name of a pointer to an integer. Arrays are commonly handled
with a pointer to the first element so it could be a pointer to an array.
int abc[];
'abc' is not a pointer. It is the name of an array. The declaration is
incomplete because the number of elements is not given.
The following is not completely specified becaus of the missing array
dimension.
-----------
enum TYPE {INT, STRING, COLOR};
struct Command
{
char * m_name;
TYPE m_params[];
int m_paramsCount;
};
-----------
The following has 4 'TYPE' items IN the structure. If the dimension of
m_params is changed, the size of the structure will change.
-----------
enum TYPE {INT, STRING, COLOR};
struct Command
{
char * m_name;
TYPE m_params[4];
int m_paramsCount;
};
-----------
The following has NO 'TYPE' items in the structure. What it contains is a
pointer to 'TYPE'. Changing the size of an array whose address 'm_params'
contains does not alter the size of the structure.
-----------
enum TYPE {INT, STRING, COLOR};
struct Command
{
char * m_name;
TYPE *m_params;
int m_paramsCount;
};
-----------
Quote
...For me, an array of ints is just like a array of chars (= string)...
Yes, except for the type of the elements in the array, both work essentially
the same. The issue relates not to an array but to the fact that an array
and a pointer to an element are very different things.
struct X
{
char char_array[6];
};
struct Y
{
char *char_pointer;
};
X xx[] = { { "x1234"; } }
Y yy[] = { { "y1234"; } }
Ignoring any alignment packing issues
sizeof(xx) is 6
sizeof(yy) is 4
X contains the array. Y contains the address of an array. A pointer is not
an array.
Quote
Please, I'd like to understand something. What is the
fundamental difference between :

struct Command { char * m_string; };
Command commands[] = { {"Flicker"} };
The struct is a declaration of a structure type whose structre contains one
element, a 'char*' or pointer to char.
The array declaration attempts to allocate an array of one structure and
initialize the 'char*' variable to the address of the first character of an
anonymous 'const char*' 0-terminated array of characters.
Quote
...But I don't see what would be different from a 16-bit
program for DOS concerning the question I have asked...
There are memory size limitations on DOS programs related to the size of the
array. Depending upon the compiler version the available option settings
related to enums are more limited.
. Ed
Quote
Mark Morrisson wrote in message
news:44c4c8ab$ XXXX@XXXXX.COM ...

The debugguer just catches a memory fault exception.

If the statement

int a[];

isn't a pointer to an array, what is it ?

Please, I'd like to understand something. What is the fundamental
difference
between :

struct Command { char * m_string; };
Command commands[] = { {"Flicker"} };

and

struct Command { int m_array[]; };
Command commands[] = { { {5, 6} } };

?

For me, an array of ints is just like a array of chars (= string),
I don't understand why the compiler should behave differently.
What's wrong in the 2nd form ? It's precisely what I'd like to
understand.

My program is just in Win32 console mode for 32-bit memory
model. Well, it's a classic program. But I don't see what would
be different from a 16-bit program for DOS concerning the
question I have asked.
 

Re:Crash...

Mark Morrisson wrote:
Quote
Well, if I replace

TYPE m_params[];
with
TYPE * m_params;

then the program does not compile anymore. I get the following error :
Cannot convert 'int' to 'TYPE *'
Correct. You cannot initialize a pointer (m_params is a pointer) in
this manner.
It would be like trying to do
int * array = {1,2,3,4,5};
instead of the proper
int array[] = {1,2,3,4,5};
Quote
So, how could I write the program ? Of course, I always have the possibility
to affect the m_params parameter dynamically with new [], but I wanted to do
it statically.
You already know you can produce variable sized structures.
That was the original problem with your code.
In order to use an array of structures, they must all be the same
size.
This can be done by using a set size for m_params, or by making
m_params a pointer to variable sized sub-arrays. (which you have
discovered, is difficult to set statically).
Try it using this, with 'max_params' set to the largest sub-array.
struct Command{
char * m_name;
TYPE m_params[max_params];
int m_paramsCount;
};
 

Re:Crash...

Ok, thank you everyone for your help.
The problem is that I tried to iterate through an array of variable-sized
elements.
I will find another way to do that.
All the best,
Mark