Visual Studio 文件输出错误

Visual Studio file output error

当我在 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] = '[=11=]';
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 并且它使用所有分配的内存作为文件名。为什么会这样?

您没有正确终止字符串:

while ((x = getchar()) != '\n'){
    ptd[i] = x;
    i++;
}
ptd[i + 1] = '[=10=]';

此处 i 在循环中递增,这样最后的 i 将已经超过构建的字符串。因此 ptd[i + 1] = '[=13=]'; 行中的额外增量将留下一个未初始化的字符。所以正确的代码是 ptd[i] = '[=14=]';

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] = '[=10=]';     <== now you move *one char more* from the last one
strcat(ptd, ".txt"); // append .txt

工作原理如下:

输入字符串(来自getchar)="abc\n"

mallocptd[]=<junk>

之后

读取标准输入后ptd[]="abc"<junk>

while 循环后 i==3 并指向剩余部分的第一个字节 <junk>;

现在 ptd[i+1]ptd[4] 设置为 0

这是 ptd 的样子:ptd[]="abc"<junk char><zero>

因为 malloc 不会将内存初始化为零(calloc 会),这恰好发生在 GCC 中为零而不是 visual studio 中的零。

为什么?

您仍然可以在 eclipse 中重现它。

ptd = (char*)malloc(150 * sizeof(char)); 行之前添加一个循环以从堆中分配并填充垃圾,以使 ptd 重用该垃圾。

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“使用调试堆查找缓冲区溢出”部分:

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.

那么,如果你看这里:http://www.idautomation.com/product-support/ascii-chart-char-set.html

你会看到:

Í 205 0xcd 0315 Í PostScript (”) hungarumlaut

就是您在文件名中看到的字符。