I am getting extra garbage at the end of the string returned by this function. Why?

char *read(char *fname)
{
    FILE *file=fopen(fname,"r");
    printf("Opening input file...\n");
    if (file==NULL)
        return NULL;
    int length=0;
    char *ret=new char[length];
    while (!feof(file))
    {
        char ch=fgetc(file);
        char *temp=new char[length+1];
        for (int i=0; i<length; i++)
            temp[i]=ret[i];
        delete[]ret;
        if (ch==EOF)
            ch=0;
        temp[length++]=ch;
        ret=temp;
    }
    fclose(file);
    return ret;
}

Let me explain a little further. In my debugger this all works fine, but when I actually run the program outside the debugger it fails... but why?

Sorry, my ideas were not gathered. Let me rephrase, I have a crash in this function but only when I run it outside the debugger. I get to the commented line before failure:

void write(char *text, char *fname)
{
    if (text==NULL)
        return;
    FILE *file=fopen(fname,"w");
    printf("Opening output file...\n");
    if (file==NULL)
        return;
    printf("Printing to file...\n");
    for (int i=0; text[i]; i++)
    {
        fputc(text[i],file);//failure here... but why?!
        printf("%c",text[i]);
    }
    printf("Done printing to file...\n");
    fclose(file);
}

i must be going out of bounds for the array text.

In your first code, why are you using new to get temp then you delete ret?

The code for read() works fine, its write() that is only working in the debugger and not outside of it. When I debug the program executes with no problem and with the expected output, but when I just run it outside the debugger it crashes and a windows error report screen pops up. Why does my write() function fail only outside the debugger?

I attached a word document that better explains using pictures. This has me stumped, I cannot think of any reason why the debugger can run the code successfully but outside it the code fails.

Attachments
#include <stdio.h>
#define IFNAME "input.txt"
#define OFNAME "output.txt"
int len(const char *str)
{
    int i;
    for (i=0; str[i]; i++){}
    return i;
}
char *read(char *fname)
{
    FILE *file=fopen(fname,"r");
    printf("Opening input file...\n");
    if (file==NULL)
        return NULL;
    int length=0;
    char *ret=new char[length];
    while (!feof(file))
    {
        char ch=fgetc(file);
        char *temp=new char[length+1];
        for (int i=0; i<length; i++)
            temp[i]=ret[i];
        delete[]ret;
        if (ch==EOF)
            ch=0;
        temp[length++]=ch;
        ret=temp;
    }
    fclose(file);
    return ret;
}
void write(char *text, char *fname)
{
    if (text==NULL)
        return;
    FILE *file=fopen(fname,"w");
    printf("Opening output file...\n");
    if (file==NULL)
        return;
    printf("Printing to file...\n");
    for (int i=0; text[i]; i++)
    {
        fputc(text[i],file);//failure here... but why
        printf("%c",text[i]);
    }
    printf("Done printing to file...\n");
    fclose(file);
}
char *replaceAll(char *text, char  find, const char *replace)
{
    int rlen=len(replace);
    int numfound=0;
    for (int i=0; text[i]; i++)
    {
        if (text[i]==find)
            numfound++;
    }
    char *ret=new char[len(text)+numfound*rlen+1];
    int ri=0;
    for (int i=0; text[i]; i++)
    {
        if (text[i]!=find)
            ret[ri++]=text[i];
        else
        {
            for (int ii=0; ii<rlen; ii++)
                ret[ri++]=replace[ii];
        }
    }
    ret[ri]=0;
    delete[]text;
    return ret;

}
int log(int x)
{
    int ret=0;
    while (x>0)
    {
        x/=10;
        ret++;
    }
    return ret;
}
char *replaceAllInc(char *text, char find, int startindex)//replace find with incrementing number
{
    int num=startindex;
    for (int i=0; text[i]; i++)
    {
        if (text[i]==find)
        {
            text[i]=-1;
            char *rep=new char[log(num)+1];
            sprintf(rep,"%i",num++);
            text=replaceAll(text,-1,rep);
            delete[]rep;
        }
    }
    return text;
}
char *insertBefore(char *text, int index, char insert)
{
    char *ret=new char[len(text)+2];
    for (int i=0; i<index; i++)
        ret[i]=text[i];
    ret[index]=insert;
    for (int i=index; text[i]; i++)
        ret[i+1]=text[i];
    ret[len(text)+1]=0;
    delete[]text;
    return ret;
}

char *highlight(char *text)
{
    if (text==NULL)
        return NULL;
    int length=len(text);
    char *keywords[]={
        "asm ", "auto ", "bool ", "break ", "case ", "catch ",
        "char ", "class ", "const ", "const_cast ", "continue ",
        "default ", "delete ", "do ", "double ", "dynamic_cast ",
        "else ", "enum ", "explicit ", "export ", "extern ",
        "false ", "float ", "for ", "friend ", "goto ", "if ",
        "inline ", "int ", "long ", "mutable ", "namespace ",
        "new ", "operator ", "private ", "protected ", "public ",
        "register ", "reinterpret_cast ", "restrict ", "return ",
        "short ", "signed ", "sizeof ", "static ", "static_cast ",
        "struct ", "switch ", "template ", "this ", "throw ",
        "true ", "try ", "typedef ", "typeid ", "typename ",
        "union ", "unsigned ", "using ", "virtual ", "void ",
        "volatile ", "while ", "int8_t ", "uint8_t ", "int16_t ",
        "uint16_t ", "int32_t ", "uint32_t ", "int64_t ", "uint64_t ",
        "int_least8_t ", "uint_least8_t ", "int_least16_t ",
        "uint_least16_t ", "int_least32_t ", "uint_least32_t ",
        "int_least64_t ", "uint_least64_t ", "int_fast8_t ",
        "uint_fast8_t ", "int_fast16_t ", "uint_fast16_t ",
        "int_fast32_t ", "uint_fast32_t ", "int_fast64_t ",
        "uint_fast64_t ", "intptr_t ", "uintptr_t ", "intmax_t ",
        "uintmax_t ", "wint_t ", "wchar_t ", "wctrans_t ",
        "wctype_t ", "size_t ", "time_t ", "and ", "and_eq ",
        "bitand ", "bitor ", "compl ", "not ", "not_eq ", "or ",
        "or_eq ", "xor ", "xor_eq ", "complex ", "imaginary ",
        "_Complex ", "_Imaginary ", "_Bool ", "_Pragma ", 0
    };
    char *dockeywords[]={
        "a", "addindex", "addtogroup", "anchor", "arg", "attention",
        "author", "b", "brief", "bug", "c", "class", "code", "date",
        "def", "defgroup", "deprecated", "dontinclude", "e", "em",
        "endcode", "endhtmlonly", "endif", "endlatexonly", "endlink",
        "endverbatim", "enum", "example", "exception", "f$", "f[", "f]",
        "file", "fn", "hideinitializer", "htmlinclude", "htmlonly", "if",
        "image", "include", "ingroup", "internal", "invariant",
        "interface", "latexonly", "li", "line", "link", "mainpage", "name",
        "namespace", "nosubgrouping", "note", "overload", "p", "page",
        "par", "param", "post", "pre", "ref", "relates", "remarks", "return",
        "retval", "sa", "section", "see", "showinitializer", "since", "skip",
        "skipline", "struct", "subsection", "test", "throw", "todo",
        "typedef", "union", "until", "var", "verbatim", "verbinclude",
        "version", "warning", "weakgroup", "$", "@", "\"", "<", ">", "#",
        "{", "}", 0
    };
    #define CODE 1
    #define COMMENT 2
    #define MLCOMMENT 3
    #define DOC 4
    #define MLDOC 5
    #define PREPROCESSOR 6
    #define STR 7
    #define CHR 8
    #define ENDSTR 9
    #define ENDCHR 10
    #define KEYWORD 11
    #define DOCKEYWORD 12
    #define OPERATOR 13
    #define NUMBER 14
    #define ENDL 15
    char *format=new char[len(text)+1];
    char state=CODE;
    for (int i=0; text[i]; i++)
        format[i]=CODE;
    format[len(text)]=0;
    printf("Loading format string...\n");
    for (int i=0; text[i]; i++)
    {
        if (((i*1000)/(length*10))%5==0)
            printf("%i%% formatted...\n",(i*100)/length);
        if (text[i]=='\n'&&state!=MLCOMMENT&&state!=MLDOC)
            state=ENDL;
        switch (state)
        {
            case OPERATOR:
            case CODE:
            case ENDL:
            switch (text[i])
            {
                case '#':
                    if (i==0||text[i-1]=='\n')
                        state=PREPROCESSOR;
                    break;
                case '/':
                    if (text[i+1]=='/')
                    {
                        if (text[i+2]=='/'||text[i+2]=='!')
                            state=DOC;
                        else
                            state=COMMENT;
                    }
                    else if (text[i+1]=='*')
                    {
                        if (text[i+2]=='*'||text[i+2]=='!')
                            state=MLDOC;
                        else
                            state=MLCOMMENT;
                    }
                    else
                        state=OPERATOR;
                    break;
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                case '0':
                    state=NUMBER;
                    break;
                case '\"':
                    state=STR;
                    break;
                case '\'':
                    state=CHR;
                    break;
                case '<':
                case '>':
                case '=':
                case '|':
                case '%':
                case '^':
                case '&':
                case '*':
                case '(':
                case ')':
                case '+':
                case '-':
                case '~':
                case '.':
                case '{':
                case '}':
                case '[':
                case ']':
                case ':':
                case ';':
                case '!':
                    state=OPERATOR;
                    break;
                default://check for keyword
                    for (int ii=0; keywords[ii]!=0; ii++)
                    {
                        bool hit=true;
                        for (int iii=0; keywords[ii][iii]&&text[i+iii]&&hit; iii++)
                        {
                            if (text[i+iii]!=keywords[ii][iii])
                                hit=false;
                        }
                        if (hit)
                        {
                            state=KEYWORD;
                            break;
                        }
                    }
                    if (state!=KEYWORD)
                        state=CODE;
                    break;
            }
            break;
            case MLCOMMENT:
                if (text[i]=='*'&&text[i+1]=='/')
                    state=CODE;
                break;
            case MLDOC:
                if (text[i]=='*'&&text[i+1]=='/')
                {
                    state=CODE;
                    break;
                }
            case DOC:
                if (text[i]=='@')
                {
                    for (int ii=0; dockeywords[ii]!=0; ii++)
                    {
                        bool hit=true;
                        for (int iii=0; dockeywords[ii][iii]&&text[i+iii]&&hit; iii++)
                        {
                            if (text[i+iii]!=dockeywords[ii][iii])
                                hit=false;
                        }
                        if (hit)
                        {
                            state=DOCKEYWORD;
                            break;
                        }
                    }
                }
                break;
            case PREPROCESSOR:
                if (text[i]=='/')
                {
                    if (text[i+1]=='/')
                    {
                        if (text[i+2]=='/'||text[i+2]=='!')
                            state=DOC;
                        else
                            state=COMMENT;
                    }

It seems to me that this piece of code is suspicious, in the "highlight" function, towards the end, you have:

char *temp=new char[len(text)+108];
    sprintf(temp,"<table width=\"100%%\" border=\"0\" cellspacing=\"0\">\n<tr>\n<td>1.</td>\n<td bgcolor=\"#FFFFFF\">%s</span></td>\n</tr>\n</table>",text);

I counted 116 additional characters (considering the newlines to be one character, which is not the case on all OSes). You should be using strcat instead.

I highly, highly recommend that you use std::string instead of C-style strings. I mean, all the code you have would be a heck of a lot more robust, faster and simpler if you used std::string instead.

Usually when you have code that works fine in debug mode and crashes or misbehaves in normal or release mode, it usually means that you have a memory corruption problem. Usually, debug-runs have additional code that fills any uninitialized memory with dummy values (like 0 or some hex pattern like 0xBAADF00D ). So, if your code happens to work fine in debug mode it is usually due to accessing memory that is either uninitialized or unused or used by something else and happens to have been zeroed, when in release mode that is no longer the case and your program crashes. In other words, the main thing that changes between debug and release execution modes is the resulting memory pattern and "empty" values, which should not have any effect on your code as long as you are not accessing memory that you shouldn't access and that you are not using uninitialized memory. In your case, and by seeing your code, I suspect you are doing both, and using std::string instead could pretty much insure that your do neither.

Ok, I changed those lines to:

char *temp=new char[len(text)+len("<table width=\"100%%\" border=\"0\" cellspacing=\"0\">\n<tr>\n<td>1.</td>\n<td bgcolor=\"#FFFFFF\">")+len("</span></td>\n</tr>\n</table>")];
    sprintf(temp,"<table width=\"100%%\" border=\"0\" cellspacing=\"0\">\n<tr>\n<td>1.</td>\n<td bgcolor=\"#FFFFFF\">%s</span></td>\n</tr>\n</table>",text);

just for a temporary fix. I am now working on converting it to std::string. I guess I just thought that using c-strings would be faster since I don't need all the functionality of an std::string. I guess I was wrong. Thanks!

>>I guess I just thought that using c-strings would be faster since I don't need all the functionality of an std::string. I guess I was wrong. Thanks!

In C++, the default choice should always be std::string , it will always be easier than C-style strings and usually faster in execution time too (or the same, depending on your skill at writing the C-style version of the code). C-style strings only appear in special circumstances (like interfacing with a C library). Then there are more advanced applications where std::string isn't sufficient and where more feature-rich tools are required (anything from std::stringstream , to boost::tokenizer , to boost::spirit ). But, the default is always std::string , because if you don't need all its features, the compiler won't make you pay a performance penalty (or additional code) for the features you don't use, so don't be afraid to use it even in the simplest use-cases.

This question has already been answered. Start a new discussion instead.