When I build the code bellow on eclipse everything works as expected on the command line and everything looks as it should be on the output file.
#include <stdio.h>
#include <stdlib.h> // for exit()
#include <string.h>
int main(int argc, char *argv[])
{
FILE *in, *out; // declare two FILE pointers
int ch;
// check for command-line arguments
if (argc < 2)
{
fprintf(stderr, "Usage: %s filename\n", argv[0]);
exit(EXIT_FAILURE);
}
// set up input
if ((in = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "I couldn't open the file \"%s\"\n",
argv[1]);
exit(EXIT_FAILURE);
}
// set up output
char *ptd;
ptd = (char*)malloc(150 * sizeof(char));
char x;
int i = 0;
while ((x = getchar()) != '\n'){
ptd[i] = x;
i++;
}
ptd[i + 1] = '\0';
strcat(ptd, ".txt"); // append .txt
if ((out = fopen(ptd, "w")) == NULL)
{ // open file for writing
fprintf(stderr, "Can't create output file.\n");
exit(3);
}
// copy data
while ((ch = getc(in)) != EOF)
putc(ch, out); // print every 3rd char
// clean up
if (fclose(in) != 0 || fclose(out) != 0)
fprintf(stderr, "Error in closing files\n");
free(ptd);
return 0;
}
but when I build it with visual studio, I get this thing "Í" after my file name 'till it reaches .txt and it uses all the allocated memory for the file name. Why is this happening?
int i = 0;
while ((x = getchar()) != '\n'){
ptd[i] = x;
i++; <=== increment, hence 'i' points to the char *after* the last one
}
ptd[i + 1] = '\0'; <== now you move *one char more* from the last one
strcat(ptd, ".txt"); // append .txt
here's how it works:
input string (from getchar
)="abc\n"
after malloc
ptd[]=<junk>
after reading stdin ptd[]="abc"<junk>
after the while loop i
==3 and points to the first byte of the rest of <junk>
;
now ptd[i+1]
which is ptd[4]
is set to 0
here's how ptd looks like: ptd[]="abc"<junk char><zero>
since malloc
does not initialize memory to zeroes (calloc
does) it just happened for you that in GCC was zero and not zero in visual studio.
Why?
You still can reproduce this in eclipse as well.
before the line ptd = (char*)malloc(150 * sizeof(char));
add a loop to allocate from heap and fill in with garbage, to make ptd
reuse that garbage.
char *p[20];
int n,j;
for(n=0;n<20;++n)
{
p[n]=(char*)malloc(150 * sizeof(char));
for(j=0;j<150;++j)
{
p[n][j]=(char)n*11+j+3;
}
}
for(n=0;n<20;++n)
{
free(p[n]);
}
What that means is (probably) a program compiled with GCC starts with clean heap, while MSVC starts with heap filled with garbage.
MSVC can do that when it fills heap with a garbage which helps detect the kind of human errors like the one you did.
Have a look at this page: https://msdn.microsoft.com/en-us/library/974tc9t1.aspx section "Find buffer overruns with debug heap":
The debug heap also fills new memory blocks with a known value.
Currently, the actual byte values used are as follows:
New objects (0xCD)
New objects are filled with 0xCD when they are allocated.
then, if you look here: http://www.idautomation.com/product-support/ascii-chart-char-set.html
you will see:
Í 205 0xcd 0315 Í PostScript (”) hungarumlaut
is the very character which you saw in your filename.