Reputation: 311
I am doing an exercise in C to brush myself up on the topic. I am trying to use my program to manipulate header files; but the program returns "Segmentation fault". I have isolated the issue to the following segment of code. Can any one help me see what exactly is wrong with it ?
header=strtok(st,"\"");
header=strtok(NULL,"\"");
f=fopen(header,"r");
if(f)
{
while((ch=fgetc(f))!=EOF)
fputc(ch,f2);
fclose(f);
}
else
{
header2=(char *)malloc(strlen("/usr/include")+strlen(header));
header2=strcat("/usr/include/",header);
f=fopen(header2,"r");
printf("%s\n",header2);
while((ch=fgetc(f))!=EOF)
fputc(ch,f2);
fclose(f);
}
I have noted that the issue occurs only when I am trying to access the /usr/include/ location. Some sort of authentication issue ? If so, how to over come it ? Thanks in advance. :)
Upvotes: 1
Views: 103
Reputation: 134326
The major problem is in
header2=strcat("/usr/include/",header);
as you're supplying a string literal as the destination. This does not have any space to hold the concatenated string. So, you're essentially trying to access invalid memory which invokes undefined behavior.
That said, for strcat()
, the behavior is, (emphasis mine)
The
strcat()
function appends thesrc
string to thedest
string, overwriting the terminating null byte ('\0'
) at the end ofdest
, [...]
which, in your case, involves an attempt to modify a string literal, which again, invokes UB.
Then, there are more to point out, like
strlen()
does not count the terminating null-byte for a string, so using strlen()
for allocating memory should contain a +1
as the size to get the space for the null-termination.
Please see this discussion on why not to cast the return value of malloc()
and family in C
..
fopen()
for success before using the return value.Upvotes: 2
Reputation: 780974
You can't use a string literal as the target of strcat
-- string literals are not modifiable, and it doesn't have enough space to hold the concatenated string. A better way to combine the variable with a prefix is with sprintf
.
header2 = malloc(strlen("/usr/include/")+strlen(header)+1);
sprintf(header2, "/usr/include/%s", header);
Note that you need to add 1 to the combined lengths when calling malloc()
, to allow space for the trailing null byte.
You could also use strcpy
followed by strcat
:
strcpy(header2, "/usr/include/");
strcat(header2, header);
Upvotes: 3