Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

problem with iterated new operator 1

Status
Not open for further replies.

bodhi

Programmer
Jan 3, 2002
67
GB
Hi all,

I'm writing a language file parsing utility and have a hit a brick wall using the new operator.

I have a struct for keywords as follows :
Code:
 struct KEYWORDBIN
         { INT keywordindex;
           CHAR name[MAX_STR_SIZE];
           BOOL iscasesensitive;
           COLOUR colour;
           CHAR keywords[][MAX_KWD_LENGTH];
         };
The keywordbin belongs in turn to a language struct as follows :

Code:
        // Top Level Language Information container :
struct LANGUAGE
 { LANGUAGEHEADER lheader;
   KEYWORDBIN keywordinfo[MAX_KEYWORD_TYPES];  };
Both of these structs are protected within the DATACOLLECTOR class.

I have a top level parse function that handles collating the info from an unknown number of keyword groups in a file.

Code:
BOOL DATACOLLECTOR::parselanguagekeywords (LANGUAGE *lng, FILE *fp)
/* This is the engine for parsing a keyword lists for a specific language.12 types of keywords are allowed per language and each is customisable in terms of colour and case sensitivity etc..
*/
 { INT kwdcount = 0;
   CHAR *lptr = NULL;
   INT kwdnum;

   // Verify file pointer location :
   fgets(linerecord,MAX_LINE_LENGTH,fp);
   while ((lptr = strstr(linerecord,"/K")) != NULL)
    { getint (&(lptr+2),&kwdnum);
      if (kwdnum > MAX_KEYWORD_TYPES)
       { // error msg here..
         return FALSE;
       }

      if (kwdnum != kwdcount)
       { //log msg here..
       }

      // All goes Pete Tong here 2nd time round.
      kwdcount++;
      KEYWORDBIN *kwd = new KEYWORDBIN;
      kwd->keywordindex = kwdnum;

      if (!getkeywordheader(kwd,linerecord))
       { //error msg here..
         return FALSE;
       }

      // Parse the keywords themselves for this keyword group :
      if (getkeywords(fp,kwd->keywords) == 0)
         return FALSE;

      // Add the keyword group to the language :
      lng->keywordinfo[kwdcount-1] = *kwd;
    }
   return TRUE;
 }
The first keyword group is parsed correctly but, running through my while loop a second time, the program UAE's when I try to create the keywordbin.
KEYWORDBIN *kwd = new KEYWORDBIN;
I'm totally bamboozled as to why this is happening - any help or pointers would be most welcome. Does this sort of problem mean I've dropped the ball elsewhere (any ideas what I should be looking for?) or am I missing something...

Thx.
 
Further to my last post this all works if I change the dynamic array in keywordbin to be static
e.g
Code:
CHAR keywords[MAX_NUM_KEYWORDS_PER_GROUP][MAX_KWD_LENGTH];

I can sort of see that there might be problems creating objects where the compiler cant tell the size of the object (as with the dynamic array situation) but then how does the new operator work with classes ?

I must be fouling the field somewhere - any help understanding whats happening would be great.

 
Don't declare
Code:
CHAR keywords[][MAX_KWD_LENGTH];
as a real variable. It's wrong in C and C++. VC calls this construct as nonstandard extension used : zero-sized array in struct/union, but it's wrong construct, but it's more better to diagnose this construct on error, not warning severity level.

Indeed, we don't know a size of that 'array' (and compiler does not know). There is no any allocation for that 'array'. Your program disrupts its memory when write via
Code:
keyword[m][n]
.

You may use
Code:
array[][n]
declarator in a function parameter list only. It means as 'pointer to 2D array with n elements in each row'. It's callee's responsibity to allocate memory for that array.

There are many ways to correct this situation. For example, you may:
Code:
typedef CHAR Kw[MAX_KWD_LENGTH];
struct KeywordBin
{
  INT    keywordindex;
  CHAR   name[MAX_STR_SIZE];
  BOOL   iscasesensitive;
  COLOUR colour;
  Kw*    keywords;
  KeywordBin(int n = 100) { keywords = new Kw[n]; }
  ~KeywordBin() { delete [] keywords; }
};
See alloc/dealloc in constructor and destructor. Now you can declare:
Code:
KeywordBin kwb64(64); // or
KeywordBin kwb; // for 100 keywords, or
KeywordBin* pkwb = new KeywordBin(32); // alloc in the heap.
May be, it's a good time to redesign a keyword list representation, but it's the other story...

Apropos, it's not the best way to use all capitals names for your classes (a structure is a class with all public members in C++)...
 
Thankyou very much ArkM - that explains where I've gone wrong.

I think, as you say, some rethinking architecturally is required but I understand the problem now.

Appreciate the help.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top