Why does this program run in the ddd debugger but when i try to run the
program in a konsole i get a segmentation fault. I just can't work it out
the OS i use is suse 8.2 pro program below:
Your program produces different results during different executions
because it invokes undefined behavior (UB). UB need not be consistent
between systems. It need not even be repeatable on the same system.
As you have just discovered, when you are UNlucky, UB has the
appearance of working as designed. This leads to a false sense of
success and later a bit of shock when the UB has the good graces to
abort your program in a way that says something is really wrong.
In your case, the particular undefined behavior is attempting to
modify a string literal constant as described below.
/* OVERLAY.C OVERLAY OF STRINGS */
#include<malloc.h>
There is no malloc.h in the standard. You probably want stdlib.h
where malloc is prototyped.
#include<string.h>
#include<stdio.h>
#define MAX_LEN 40
int main(void)
{
int pos;
char *line, *aster, *blank;
line = (char*)malloc(MAX_LEN);
Don't cast the return from malloc if it is being assigned to a
pointer. Since malloc returns a pointer to void which is, by
definition, compatible with any other object pointer, it can never
help. On the other hand, it can cause the compiler to suppress a
warning message regarding your failure to include stdlib.h which would
cause your program to invoke UB. For the same reason discussed in
aster, you need MAX_LEN+1.
aster = (char*)malloc(1);
Due to the mistake noted below, you don't use the three addresses you
receive from malloc. When you correct that mistake, aster will need
to point to an area at least two bytes long. This is because every
string must terminate with a '\0' and the compiler does this
automatically for quoted string literals. Thus, the string "*"
consists of the two characters '*' and '\0'.
blank = (char*)malloc(1);
You apparently intend blank to point to the area in memory where the
result of your string manipulation will reside. You must allocate
enough space to hold the worst case result, which is 42 bytes (40
possible characters from line plus two from aster).
This statement says "Ignore the value currently in line and replace it
with the address of the string literal." The value currently in line
points to an allocated area. line is the only variable which contains
this value. Once the value is replaced, you have no way to recover
it. This means you can never free the area you allocated. This is a
memory leak. Since you never attempt to modify the data pointed to by
line, you could delete the malloc above to eliminate this problem.
If you really want line to point to a modifiable string, then instead
of an assignment statement you should use strcpy:
strcpy(line, " ");
Ditto for aster
Ditto for blank but it is worse because you do modify the data it
points to.
blank points to the string literal "". The literal is, by
definition, a non-modifiable array of char (in this case, an array of
one char whose value is '\0'). For historical reasons, the literal is
not treated as const. Nonetheless, you are not allowed to modify it.
Attempting to do so invokes UB.
Even if you were allowed to modify it, the area reserved for the
array is only one byte long. As soon as you try to concatenate
anything on to it, you invoke UB by overflowing the array.
While the strcpy approach described above will work, it is overkill.
The empty string consists of only one char and you could achieve the
same effect with a simple
*blank = '\0';
printf("Enter position of star(1 - 41): ");
stdout may be buffered. Your output may not yet be visible when the
scanf executes. You can force it to be visible by adding the
statement
fflush(stdout);
scanf("%d",&pos);
if(pos > 0 && pos < 41)
To allow a value of 41, use <= or < 42.
{
printf("\n");
printf(" 1 2 3 4\n");
printf("1234567890123456789012345678901234567890\n");
puts(strcat (strncat(blank,line,pos-1),aster));
}
else
printf("out of range %d\n",pos);
return 0;
}
<<Remove the del for email>>