We help IT Professionals succeed at work.
Get Started

Program runs fine in Microsoft Visual C++ debugger, but crashes outside the debugger.

starkman
starkman asked
on
320 Views
Last Modified: 2008-01-09
I'm running the following program, which truncates any text string longer than 32000 characters to 32000 characters. When the number of text string "nchar" is about 90000,  here is what I observed:

1). When I run it through Microsoft Visual C++ debugger, it seems to work fine.

2). When I run it outside Microsoft Visual C++ debugger, it crashes at the following line of code:
pBuf = (InlineBuf *)fcalloc(1, sizeof(InlineBuf));

3). Since the observations 1) and 2) strongly suggests that there is a memory overflow, I did a Purify test, which reports the following two memory errors:
Error 1: ABW: Array bounds write  (2 times) -- Writing 22 bytes to 0x34b736 in the heap (13 bytes at 0x34b73f illegal)
Error 2: ABR: Array bounds read  (2 times) -- Reading 18 bytes from 0x34b73a in the heap (13 bytes at 0x34b73f illegal)
However, I noticed that the above two memory errors reported by Purify both occured before the line of code that crashes.

4). When the number of text string "nchar" is less than 32000, the program works fine.

5). When the number of text string "nchar" is about 40000, the program crashes at the same place, and Purify reports the nearly the same memory errors except that there are no "(2 times)" in the error messages.

Something to be done soon: while posting this question, I'm waiting for doing another Purify test, which is to run the program when nchar is less than 32000 to see if the two memory errors still occur. However, our Purify build of today is temporarily not ready, but I'll do the test as soon as it's ready and let you know the result.

Please advise on where the problem could be.

Thank you in advance for your help!


#define LIST_INFO(type)  type *next; \
    type *tail; \
    type *previous;

typedef struct inlineBuf_s
{
    LIST_INFO(struct inlineBuf_s)
    char line[SS_MAX_TEXT_LEN + 1];
}
InlineBuf;

#define SS_MAX_TEXT_LEN     32000

#define fcalloc calloc

/* sswsty(): called from ontab() when it sees "ON TABLE/GRAPH SET  */
/* STYLE/GRAPHSTYLE *", or from ssset() when it sees "SET STYLE=*" */
/* (PUTSTYLE). */
/* Copies the in-line stylesheet following the above, up to */
/* "ENDSTYLE" or "END", into a buffer in memory. */
/* 'inlineType' parameter is one of the IS_* constants in sshdr.h. */
 
long sswsty (t_cbh *cbh, long inlineType)
{
    t_stylcm  *  stylcm = (t_stylcm  *) cbh->cb[C_STYLCM];
    t_ptbcm   *   ptbcm = (t_ptbcm   *) cbh->cb[C_PTBCM];
    t_pipeds  *  pipeds = (t_pipeds  *) cbh->cb[C_PIPEDS];
    t_currnt  *  currnt = (t_currnt  *) cbh->cb[C_CURRNT];
    long rc = 0;
    InlineBuf *pBuf;
    InlineBuf *pLongBuf;
    BOOL_ truncated = FALSE;
    BOOL_ needTruncation = FALSE;
    BOOL_ previousLineEndedByDollarSignNaturally = TRUE;
    BOOL_ isNewStyleSheetStatement = FALSE;

    /* If FORECASTing, the style is parsed twice.  However,           */
    /* stylcm->inlineList is only freed (in cerrget() or if an error  */
    /* occurred in sstcl3()) the final time, resulting in Memory      */
    /* Leaks.  The same is true for stylcm->inlineGraph, which is     */
    /* only freed the final time in sstcl3().  Therefore, ensure that */
    /* inlineList and inlineGraph are freed before re-use.            */
    /*                                    - BSK: MIPS 98423 PNO 50823 */
    /* PUTSTYLE stylesheets are cumulative, and are only freed at */
    /* the end of a TABLE request (sstcl3()), so don't free: */
    if (inlineType != IS_PUTSTYLE)
        freeInlineStyle(cbh, inlineType);
 
    while (TRUE)
    {
        long nchar, retcod;
        long numLBlk = 0;
        char *pstyBuf = stylcm->styleLine;
 
        /* read from pooled tables stack */
        if (ptbcm->Head_stack) {
          long ne;
          ptbget(cbh, &nchar, stylcm->styleLine, &ne);
        }
        else {
          /* Take Behavior from NEXT FORTRAN else when REQCTL is call
             a second time because of AUTOINDEX, the pipe will not
             contain the inline style */
          if (pipeds->hasdat) {
              pipein(cbh, &nchar, stylcm->styleLine, &retcod);
              if(retcod) termin(&nchar, stylcm->styleLine, &retcod);
          }
          else {
              termin(&nchar, stylcm->styleLine, &retcod);
          }
          if (ptbcm->ptph == PTPHDY) {
            char hold_line[LINELIMEDA];
            long hold_ichar = currnt->ichar, c__0 = 0;
            currnt->ichar = nchar;
            memcpy(hold_line, currnt->line, (short)nchar);
            memcpy(currnt->line, stylcm->styleLine, (short)nchar);
            addsrc(cbh, &c__0);
            memcpy(currnt->line, hold_line, (short)nchar);
            currnt->ichar = hold_ichar;
          }
        }
 
        if ((pipeds->record==1)&&(&nchar!=0)&&(pipeds->recerr<1)) {
            chkpip ( cbh, stylcm->styleLine, &nchar, &retcod );
            if ( !retcod )
                rectok(cbh, stylcm->styleLine, &nchar);
            pipeds->recerr=0;
        }
        if (nchar <= 0) break;
 
        /* If 'ENDSTYLE' at beginning of line, we're done: */
        /* Count number of leading blanks */
        numLBlk = cvscnne(nchar, pstyBuf, ' ') - 1;
        if (numLBlk < 0) numLBlk = 0;
        /* Truncate leading blanks and get resulting number characters */
        pstyBuf += numLBlk;
        nchar = cvscnneb(nchar-numLBlk, pstyBuf, ' ');
        if ((nchar == 8) && (memcmp(pstyBuf, "ENDSTYLE", 8) == 0))
            break;
 
        /* If 'END', 'RUN' or 'QUIT', we're done: */
        endr(&rc, &nchar, pstyBuf);
        if (rc != 0) {
            if (pipeds->record == 1)     /* Recording TABLE request? */
            {
                long zero = 0;
                rectok(cbh, " ",&zero);
                pipeds->record=0;        /* Stop recording */
            }
 
            /* For FORECAST, it is essential that currnt->text */
            /* contain the word "END" if it was found (see code */
            /* in tabctl.c after call to reqctl()): */
            memcpy(currnt->text, stylcm->styleLine, 8);
 
            break;
        }

        if (ptbcm->ptph == PTPHDY)
            continue;

        if (truncated && !isNewStyleSheetStatement) {
            long equalSign = cvscneqb(nchar, stylcm->styleLine, '=');                    
            long closingQuote = cvscneqb(nchar, stylcm->styleLine, '\'');
            BOOL_ hasMoreKeywords = (equalSign - closingQuote) > 0;

            if (hasMoreKeywords) {
                long comma = cvscneq(nchar - closingQuote, stylcm->styleLine + closingQuote, ',');
                nchar -= closingQuote + comma;
                pstyBuf = stylcm->styleLine + closingQuote + comma;

                pLongBuf->line[SS_MAX_TEXT_LEN - 1] = ' ';
                truncated = FALSE;
            }
            else {
                previousLineEndedByDollarSignNaturally = (*(stylcm->styleLine + nchar -1) == '$') ? TRUE: FALSE;
                isNewStyleSheetStatement = previousLineEndedByDollarSignNaturally ? TRUE: FALSE;
                continue;
            }
        }
 
        /* 36575 restore a pstyBuf pointer and nchar for truncated
           leading blank */
        if (numLBlk > 0) {
           nchar += numLBlk;
           pstyBuf = stylcm->styleLine;
        }
 
        if (nchar > SS_MAX_TEXT_LEN) {
            nchar = SS_MAX_TEXT_LEN;
            truncated = TRUE;
            needTruncation = TRUE;
        }

        /* Allocate a new buffer for this line, and link it */
        /* into the appropriate list: */    
        pBuf = (InlineBuf *)fcalloc(1, sizeof(InlineBuf));
       
        memcpy(pBuf->line, pstyBuf, nchar);
        pBuf->line[nchar] = '\0';
       
        if (needTruncation) {
            pBuf->line[nchar - 3] = '\'';
            pBuf->line[nchar - 2] = ',';
            pBuf->line[nchar - 1] = '$';

            pLongBuf = pBuf;
            needTruncation = FALSE;
        }

        switch (inlineType) {
            case IS_STYLE:
                ListAddTail(&stylcm->inlineList, pBuf);
                break;
            case IS_GRAPHSTYLE:
                ListAddTail(&stylcm->inlineGraph, pBuf);
                break;
            case IS_PUTSTYLE:
                ListAddTail(&stylcm->putstyleHead, pBuf);
                break;
        }
    }
 
    /* Put an ENDLAYOUT keyword at the end of the buffer to tell */
    /* the parser where the LAYOUT statements end and the regular */
    /* stylesheet begins: */
    if (inlineType == IS_PUTSTYLE) {
        pBuf = (InlineBuf *)fcalloc(1, sizeof(InlineBuf));
        strcpy(pBuf->line, "ENDLAYOUT, $");
        ListAddTail(&stylcm->putstyleHead, pBuf);
    }
 
    if ((rc != 3) &&                    /* Not 'QUIT'? */
        (inlineType == IS_STYLE))
    {
        /* Tell y_fopen() that we have an in-line stylesheet: */
        memcpy(stylcm->ss_file, "FOCSTY  ", 8);
    }
 
    return rc;
}
Comment
Watch Question
CERTIFIED EXPERT
Top Expert 2009
Commented:
This problem has been solved!
Unlock 1 Answer and 7 Comments.
See Answer
Why Experts Exchange?

Experts Exchange always has the answer, or at the least points me in the correct direction! It is like having another employee that is extremely experienced.

Jim Murphy
Programmer at Smart IT Solutions

When asked, what has been your best career decision?

Deciding to stick with EE.

Mohamed Asif
Technical Department Head

Being involved with EE helped me to grow personally and professionally.

Carl Webster
CTP, Sr Infrastructure Consultant
Ask ANY Question

Connect with Certified Experts to gain insight and support on specific technology challenges including:

  • Troubleshooting
  • Research
  • Professional Opinions
Did You Know?

We've partnered with two important charities to provide clean water and computer science education to those who need it most. READ MORE