当我在eclipse上构建下面的代码时,命令行上的所有内容都按预期工作,输出文件上的所有内容都按预期工作。
#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;
}
但是当我用visual studio构建它时,我会在我的文件名之后得到这个东西“Í”,直到它到达.txt并使用所有分配的内存作为文件名。为什么会这样?
最佳答案
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
其工作原理如下:
输入字符串(来自
getchar
)="abc\n"
在
malloc
ptd[]=<junk>
之后读取stdin
ptd[]="abc"<junk>
while循环后
i
==3并指向<junk>
其余部分的第一个字节;现在
ptd[i+1]
设置为ptd[4]
ptd的样子是这样的:
0
因为
ptd[]="abc"<junk char><zero>
不会将内存初始化为零(malloc
会),所以在GCC中只是发生了在visual studio中为零而不是零的情况。为什么?
您仍然可以在eclipse中重现这一点。
在
calloc
行之前,添加一个循环以从堆中分配并填充垃圾,以使ptd = (char*)malloc(150 * sizeof(char));
重用该垃圾。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]);
}
这意味着(可能)用GCC编译的程序以干净堆开始,而MSVC以充满垃圾的堆开始。
MSVC可以在堆中填充垃圾时这样做,这有助于像您这样检测人为错误。
查看此页:https://msdn.microsoft.com/en-us/library/974tc9t1.aspx部分“使用调试堆查找缓冲区溢出”:
调试堆还用已知值填充新的内存块。
目前,实际使用的字节值如下:
新对象(0xCD)
分配新对象时,将用0xCD填充它们。
那么,如果你看这里:http://www.idautomation.com/product-support/ascii-chart-char-set.html
你会看到:
Í205 0xcd 0315Í附言(“)hungarumlaut
就是你在文件名中看到的那个字符。