Problem with free()

A

Army1987

The program below works correctly, but dumps core if I add
free(str); before return 0;. The error message is somewhat more
colorful than just "Segmentation fault" (several lines long) and
seems to say "Invalid pointer".
I know free() causes UB is passed a pointer which was not returned
by an *alloc() function, but here I never change the value of str
after the call to malloc()... What is wrong?

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
char *b = "0123456789abcdefghijklmnopqrstuvwxyz_";

int main(int argc, char **argv)
{
char *a = "Chuck Norris's tears can cure cancer. "
"Too bad he's never cried. Ever.";
size_t r=0, len = strlen(a);
char *t, *str;
size_t ch = argv[1] ? (str=argv[1],(t = strchr(b,*str++))
&& (r += t-b),
r *= strlen(b),
(t = strchr(b,*str)) && (r += t-b), r) : 0;
if (ch <= len) {
putchar(a[ch]);
ch++;
fflush(stdout);
len = strlen(argv[0]);
str = malloc(len+4);
if (!str)
exit(EXIT_FAILURE);
strcpy(str, argv[0]);
str[len] = ' '; str[len+1] = b[ch/strlen(b)];
str[len+2] = b[ch%strlen(b)]; str[len+3] = 0;
system(str);
} else
putchar('\n');
return 0;
}
 
M

Michael Brennan

The program below works correctly, but dumps core if I add
free(str); before return 0;. The error message is somewhat more
colorful than just "Segmentation fault" (several lines long) and
seems to say "Invalid pointer".
I know free() causes UB is passed a pointer which was not returned
by an *alloc() function, but here I never change the value of str
after the call to malloc()... What is wrong?

If ch <= len is false str will never be set to any value
and your program will try to free an uninitalized pointer
if you put it right before return.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
char *b = "0123456789abcdefghijklmnopqrstuvwxyz_";

int main(int argc, char **argv)
{
char *a = "Chuck Norris's tears can cure cancer. "
"Too bad he's never cried. Ever.";
size_t r=0, len = strlen(a);
char *t, *str;
size_t ch = argv[1] ? (str=argv[1],(t = strchr(b,*str++))
&& (r += t-b),
r *= strlen(b),
(t = strchr(b,*str)) && (r += t-b), r) : 0;
if (ch <= len) {
putchar(a[ch]);
ch++;
fflush(stdout);
len = strlen(argv[0]);
str = malloc(len+4);
if (!str)
exit(EXIT_FAILURE);
strcpy(str, argv[0]);
str[len] = ' '; str[len+1] = b[ch/strlen(b)];
str[len+2] = b[ch%strlen(b)]; str[len+3] = 0;
system(str);
} else
putchar('\n');
return 0;
}
 
K

Kenneth Brody

Army1987 said:
The program below works correctly, but dumps core if I add
free(str); before return 0;. The error message is somewhat more
colorful than just "Segmentation fault" (several lines long) and
seems to say "Invalid pointer". [...]
int main(int argc, char **argv)
{ [...]
size_t r=0, len = strlen(a);
char *t, *str;
size_t ch = argv[1] ? (str=argv[1],(t = strchr(b,*str++))
&& (r += t-b),
r *= strlen(b),
(t = strchr(b,*str)) && (r += t-b), r) : 0;
if (ch <= len) { [...]
} else
putchar('\n');

[ "free(str);" inserted here crashes ]
return 0;
}

What happens when "ch <= len" is false?

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
C

Christopher Benson-Manica

Army1987 said:
size_t ch = argv[1] ? (str=argv[1],(t = strchr(b,*str++))
&& (r += t-b),
r *= strlen(b),
(t = strchr(b,*str)) && (r += t-b), r) : 0;

This is abjectly horrible. Why on earth do you feel the need to so
grotesquely abuse the conditional and comma operators, unless this is
going to be part of an IOCCC submission?
 
A

Army1987

Christopher Benson-Manica said:
Army1987 said:
size_t ch = argv[1] ? (str=argv[1],(t = strchr(b,*str++))
&& (r += t-b),
r *= strlen(b),
(t = strchr(b,*str)) && (r += t-b), r) : 0;

This is abjectly horrible. Why on earth do you feel the need to so
grotesquely abuse the conditional and comma operators, unless this is
going to be part of an IOCCC submission?
Don't you think that if I wasn't going to write purposefully
horrible code the program would just look like
#include <stdio.h>
int main(void)
{
puts("Chuck Norris's tears can cure cancer. "
"Too bad he's never cried. Ever.");
return 0;
}
 
A

Army1987

Michael Brennan said:
If ch <= len is false str will never be set to any value
and your program will try to free an uninitalized pointer
if you put it right before return.
Yeah. (Actually, the code I compiled ended with return free(str), str =
NULL;... then I copied and pasted the working code here. If
I had looked down before posting the fact that the place where I
was putting free() is less indented than where I called malloc()
would have made me suspect something and spot the error. Sorry.)
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
char *b = "0123456789abcdefghijklmnopqrstuvwxyz_";

int main(int argc, char **argv)
{
char *a = "Chuck Norris's tears can cure cancer. "
"Too bad he's never cried. Ever.";
size_t r=0, len = strlen(a);
char *t, *str;
size_t ch = argv[1] ? (str=argv[1],(t = strchr(b,*str++))
&& (r += t-b),
r *= strlen(b),
(t = strchr(b,*str)) && (r += t-b), r) : 0;
if (ch <= len) {
putchar(a[ch]);
ch++;
fflush(stdout);
len = strlen(argv[0]);
str = malloc(len+4);
if (!str)
exit(EXIT_FAILURE);
strcpy(str, argv[0]);
str[len] = ' '; str[len+1] = b[ch/strlen(b)];
str[len+2] = b[ch%strlen(b)]; str[len+3] = 0;
system(str);
} else
putchar('\n');
return 0;
}
 

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

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top