new和malloc分配额外的16个字节

时间:2012-02-22 07:49:22

标签: c++ malloc new-operator space extra

我在VS2010 Windows 7中编写c ++。我尝试读取大小为64字节的文件。这是代码:

    BYTE* MyReadFile(FILE *f)
{
    size_t result;
    BYTE *buffer;
    long lSize;
    if (f == NULL) 
    {
        fputs ("File error", stderr); 
        exit (1);
    }

    fseek (f, 0, SEEK_END);
    lSize = ftell (f);
    rewind (f);

    //buffer = (BYTE*) malloc (sizeof(char)*lSize);
    buffer = new BYTE[lSize];
    if (buffer == NULL) 
    {
        fputs ("Memory error", stderr); 
        exit (2);
    }

    result = fread (buffer, 1, lSize, f);
    if (result != lSize) 
    {
        fputs ("Reading error",stderr); 
        exit (3);
    }

    fclose (f);
    return buffer;
}

当我得到文件大小时它是64,但是当我用新的BYTE [lSize]为它分配内存时,我得到80个字节的空间,因此奇怪的序列ээээ««««««««оюою被添加到缓冲区的末尾。你能告诉我怎么办吗?

4 个答案:

答案 0 :(得分:4)

背后的内容称为sentinel。它用于检查您的代码是否超出已分配内存的边界。当您的程序覆盖此值时,CRT库将在您释放缓冲区时报告调试消息。

请看这里:http://msdn.microsoft.com/en-us/library/ms220938%28v=vs.80%29.aspx

enter image description here

答案 1 :(得分:4)

您分配的字节数与您看到的字节数之间存在重要差异。

如果lsize为64,那么你确实为自己分配了64个字节。这并不意味着在屏幕后面C ++运行时将向Windows提出正好64个字节。在实践中,记忆管理员要求稍微多一点的记忆,这样他们就可以做自己的功课。通常这些额外的字节是在从new / malloc返回的指针之前分配的,所以你永远不会看到它们。

然而,这不是你的问题。问题是您使用fread从文件中读取64个字节。 fread无法知道您正在阅读的数据类型。它可以是一个struct,一个char缓冲区,一组double,......它只是为你读取这些字节。

这意味着如果文件包含字符“ABC”,您将获得完全“ABC”。但是,在C中,字符串应该以空字符结尾,因此如果将此缓冲区传递给printf,它将继续扫描内存,直到找到一个空字符。

因此,要解决您的问题,请再分配1个字节,并将最后一个字节设置为nul字符,如下所示:

buffer = new BYTE[lSize+1]; 
buffer[lSize] = '\0';

答案 2 :(得分:3)

虽然这可能看起来像是一个内存问题,但它实际上是一个打印问题(正如@Mystical指出的那样)。如果要将任何内容打印为字符串,则需要设置空终止,否则在遇到一个内存(即UB)之前,内存将会被大量读取。

请改为尝试:

buffer = new BYTE[lSize + 1];
if (buffer == NULL) 
{
    fputs ("Memory error", stderr); 
    exit (2);
}

result = fread (buffer, 1, lSize, f);
if (result != lSize) 
{
    fputs ("Reading error",stderr); 
    exit (3);
}

buffer[lSize] = '\0';

它将确保在返回的缓冲区末尾有一个空终止符。

答案 3 :(得分:1)

分配内存时,不是基于每个字节。相反,它被分配在8或16字节的对齐块中(可能在开始时,在指针之前有一个头)。除非您创建大量(数百万)小对象,否则这通常不是问题。这不一定是C中的问题,甚至不是Java中的主要问题(它不支持在堆栈上分配的对象或对象的数组)。