new和malloc分配额外的16字节 我在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; }

new和malloc分配额外的16字节 我在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; },c++,malloc,new-operator,space,extra,C++,Malloc,New Operator,Space,Extra,当我得到文件大小时,它是64,但当我用新字节[lSize]为它分配内存时,我得到了80字节的空间,因此奇怪的序列被添加到缓冲区的末尾。您能告诉我如何处理这个问题吗?当分配内存时,它不是以每个字节为基础的。相反,它是在8或16字节的对齐块中分配的(可能在指针之前的开头有一个头)。这通常不是问题,除非您创建了大量(数百万)小对象。这在C中不一定是个问题,在Java中甚至不是一个主要问题(Java不支持对象数组或堆栈上分配的对象)。虽然这看起来像是内存问题,但实际上是打印问题(正如@Mystical指

当我得到文件大小时,它是64,但当我用新字节[lSize]为它分配内存时,我得到了80字节的空间,因此奇怪的序列被添加到缓冲区的末尾。您能告诉我如何处理这个问题吗?

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

虽然这看起来像是内存问题,但实际上是打印问题(正如@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';

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

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

看这里:


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

如果lsize是64,那么您确实为自己分配了64个字节。这并不意味着屏幕后面的C++运行时间将要求Windows 64个字节。实际上,内存管理器要求稍微多一些内存,这样他们就可以自己做作业了。通常,这些额外字节是在从new/malloc返回的指针之前分配的,因此您永远不会看到它们

然而,这不是你的问题。问题是您使用fread从文件中读取了64个字节。fread不可能知道您正在读取什么样的数据。它可以是一个结构,一个字符缓冲区,一组双精度码。。。它只是为您读取这些字节

这意味着,如果文件包含字符“ABC”,您将得到准确的“ABC”。但是,在C中,字符串应该以nul结尾,所以如果您将此缓冲区传递给printf,它将继续扫描内存,直到找到nul字符为止

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

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

你怎么打印出来的?如果是C字符串,则需要NULL-terminate。在
result=fread(buffer,1,lSize,f)之后插入
int buffSize=ftell(buffer)
并告诉我buffSize的值。为什么你要混合C(fSead,fTelt等)和C++(new)?你为什么不坚持其中一个呢?@Mysticial:null terminate,而不是null terminate(
null
是一个空指针常量)。@KeithThompson叹息。。。哈哈,这不是我第一次被要求这么做。了解我自己,再过5次我才会记得…:-你知道你有80字节的空间吗?正确,但与这个问题无关。有两种解决方案;不用担心,您不需要知道使用了更多的空间(16字节或临时空间在任何PC上都是微不足道的),也不需要在没有此问题的堆栈上进行分配。正确,但与此问题无关。真正的问题是nul终结者。+1我明白你的意思。他依赖于在某个随机的内存块中有一个
\0
。如果没有,他在打印时会出现总线错误,这很有效。但是你能告诉我用C++来读取/写入文件的正确方法吗?使用STD:IFStand和STD::OFFROW。有关介绍和示例,请参阅。新建后的空检查是假的。运算符new抛出异常,如果内存分配失败,则不会返回null。@Ajay:我只是复制了他的代码并解决了这个问题,而且,某些编译器/CRT impl将返回
null
并抛出异常: