Calling free() causes weird crash.

T

Tony_C

Hi All,
I come across this weird issue when using free() and malloc(). The
oringinal work is with YACC and LEX. I extract some code from it to
show what the problem is.
There are three tokens to be processed by function dummy(int index):
char* yytext_c = "anotherword";
char* yytext_a = "signed";
char* yytext_b = "thelongestofall";

function dummy(int index) compares the last token name read with
some constant string, and then saves the current token in 'last_name'.
Its only argument 'index' tell it which token (yytext_a or yytext_b or
yytext_c) to process.
'last_name' is declared and intialized as:
static char* last_name=NULL;
so that it may be re-used the next time dummy is called.

The logic seems simple (spot any errors?). However, the execution
crashes. By tracing its execution, the program crashes at this line:
free(last_name);
I am not posting the error message depends on the programming
environment and run-time library.
There are ways to avoid the crash as I figured out today, but i do
not really understand:
- in branch 1, 2 and 3, if we comment out this line
last_name = '\0';
the program will run smoothly.

- if we change the initial value of the three tokens, e.g.:
char* yytext_b = "anotherword";
char* yytext_c = "signed";
char* yytext_a = "thelongestofall";
we too may avoid the crash.

I run out of ideas after screw around for several hours. Any
suggestions on what went wrong?
thanks a lot.
--------------------
-----------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* yytext_c = "anotherword";
char* yytext_a = "signed";
char* yytext_b = "thelongestofall";

void dummy(int index){
static char* last_name=NULL;
int len,i;
char* t1 = "signed";
char* t2 = "unsigned";

if (last_name!=NULL)
printf("******* last token = %s \n",
last_name);

if (last_name!=NULL &&
strcmp(last_name,t1)!=0 && strcmp(last_name,t2)!=0)
printf("--- rule 1.1.15 ---
violated --- \n");

if( last_name != NULL )
{
free(last_name);
}


if (index==0) // branch 1, save
yytext_a
{len = strlen(yytext_a)+1;
last_name =(char*)
malloc(len*sizeof(char));
for (i=0; i<len; i++){
last_name = yytext_a;
}

last_name = '\0';
}
if (index==1) // branch 2, save
yytext_b
{len = strlen(yytext_b)+1;
last_name =(char*)
malloc(len*sizeof(char));
for (i=0; i<len; i++){
last_name = yytext_b;
}
last_name = '\0';

}

if (index>1) // branch 3, save
yytext_c
{
len = strlen(yytext_c)+1;
last_name =(char*)
malloc(len*sizeof(char));
for (i=0; i<len; i++){
last_name =
yytext_c;
}
last_name = '\0';

}
}

int main(){
int j = 0;
int limit = 5;
while (j<limit) {
dummy(j);
j++;
}
return(0);
}
 
E

Eric Sosman

[...]
The logic seems simple (spot any errors?). However, the execution
crashes. By tracing its execution, the program crashes at this line:
free(last_name);
[...]

[... reformatted for readability and sanity ...]

len = strlen(yytext_a)+1;
last_name =(char*) malloc(len*sizeof(char));
for (i=0; i<len; i++){
last_name = yytext_a;
}
last_name = '\0';


There's the error, which occurs in three places. (There may be
others, too; I haven't examined your code carefully.) When the loop
finishes, i==len so you're storing to last_name[len]. You requested
len characters, so the valid indices range from [0] to [len-1], but
[len] is out of range: You're storing outside the area you've allocated
and scribbling on something you don't own. Sometimes, it appears that
the "something" you've scribbled on is part of the data malloc() and
friends use to keep track of allocated and available memory.

Other comments:

- It's not necessary to cast the result of malloc(). A void*
converts to or from any other kinds of data pointer without
intervention.

- It's not necessary to multiply by sizeof(char), which is
necessarily equal to one.

- It *is* necessary to test whether malloc() succeeded or failed,
by comparing the result to NULL before trying to store into it.

- Have you never heard of the strcpy() or memcpy() functions?
 
M

Moi

Hi All,
I come across this weird issue when using free() and malloc(). The
oringinal work is with YACC and LEX. I extract some code from it to show
what the problem is.
There are three tokens to be processed by function dummy(int index):
char* yytext_c = "anotherword";
char* yytext_a = "signed";
char* yytext_b = "thelongestofall";

function dummy(int index) compares the last token name read with
some constant string, and then saves the current token in 'last_name'.
Its only argument 'index' tell it which token (yytext_a or yytext_b or
yytext_c) to process.
'last_name' is declared and intialized as:
static char* last_name=NULL;
so that it may be re-used the next time dummy is called.

The logic seems simple (spot any errors?). However, the execution
crashes. By tracing its execution, the program crashes at this line:
free(last_name);
I am not posting the error message depends on the programming
environment and run-time library.
There are ways to avoid the crash as I figured out today, but i do
not really understand:
- in branch 1, 2 and 3, if we comment out this line
last_name = '\0';
the program will run smoothly.

- if we change the initial value of the three tokens, e.g.:
char* yytext_b = "anotherword";
char* yytext_c = "signed";
char* yytext_a = "thelongestofall";
we too may avoid the crash.

I run out of ideas after screw around for several hours. Any
suggestions on what went wrong?
thanks a lot.
--------------------
-----------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* yytext_c = "anotherword";
char* yytext_a = "signed";
char* yytext_b = "thelongestofall";

void dummy(int index){
static char* last_name=NULL;
int len,i;
char* t1 = "signed";
char* t2 = "unsigned";

if (last_name!=NULL)
printf("******* last token = %s \n",
last_name);

if (last_name!=NULL &&
strcmp(last_name,t1)!=0 && strcmp(last_name,t2)!=0)
printf("--- rule 1.1.15 ---
violated --- \n");

if( last_name != NULL )
{
free(last_name);
}


if (index==0) // branch 1, save
yytext_a
{len = strlen(yytext_a)+1;
last_name =(char*)
malloc(len*sizeof(char));
for (i=0; i<len; i++){
last_name = yytext_a;
}

last_name = '\0';
}
if (index==1) // branch 2, save
yytext_b
{len = strlen(yytext_b)+1;
last_name =(char*)
malloc(len*sizeof(char));
for (i=0; i<len; i++){
last_name = yytext_b;
}
last_name = '\0';

}

if (index>1) // branch 3, save
yytext_c
{
len = strlen(yytext_c)+1;
last_name =(char*)
malloc(len*sizeof(char));
for (i=0; i<len; i++){
last_name =
yytext_c;
}
last_name = '\0';

}
}

int main(){
int j = 0;
int limit = 5;
while (j<limit) {
dummy(j);
j++;
}
return(0);
}



apart from what richard and Eric have said,
you can simplify your program by using a switch(level) {}
or even an array of pointers to string:

******/

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

char* texts[3] = {"anotherword", "signed", "thelongestofall"};

void dummy(int index);
char *mystrdup(const char *src);

char *mystrdup(const char *src)
{
char * new;
size_t len;

if (!src) return NULL;
len = strlen(src);
new = malloc(len+1);
/* should check malloc's return here */
memcpy(new,src,len);
new[len] = 0;
return new;
}

void dummy(int index)
{
static char* last_name=NULL;

char* t1 = "signed";
char* t2 = "unsigned";

if (last_name != NULL) printf("******* last token = %s \n", last_name);

if (last_name != NULL
&& strcmp(last_name,t1)
&& strcmp(last_name,t2)
) printf("--- rule 1.1.15 --- violated --- \n");

if (last_name != NULL ) { free(last_name);
/* this is the one */
last_name = NULL; }


if (index <0) return;
if (index>=3 ) index = 2;

last_name = mystrdup( texts[index] );
}

int main(void)
{
int j = 0;
int limit = 5;

for(j=0; j<limit; j++) {
dummy(j);
}
return 0;
}
86,0-1 98%

HTH,
AvK
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top