2012-02-03 49 views
0

我正在为统计软件包编写一些代码,并开始通过读取数据到指针数组。我初始化指针并使用malloc分配足够的内存;但是,我有时会在下面的代码末尾处分配内存错误。内存分配错误 - 在Linux中但不是OSX Unix

#include <stddef.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include "stats.h" 

int main(int argc, char **argv) { 
FILE *fp, *outFile, *outBin; // create a file identifier 
size_t n, nbins; // # of data points 
double *data; // pointer to hold data 
double average, variance, *med; // stat returns 
int medianComplete, histComplete, i; // return 1 on success 
hist_t *Histogram; 

// read in the number of bins from exe arguments 
nbins = atoi(argv[1]); 
nbins = (size_t)nbins; 

// open the binary datafile and read in first value 
// which is number of data points 
// use exe input for filename 
fp = fopen(argv[2],"rb"); 
fread(&n, sizeof(size_t),1,fp); 

// allocate enough memory to hold all data 
data = (double*)malloc(sizeof(double)*n); 
if (!data) 
    printf("Memory allocation error"); 
fread(data,sizeof(double),n,fp); 

这个程序编译和运行以及我的个人机(MacOSX的),但未能由于分段错误,当我试图在Linux服务器上运行它。我使用Valgrind来查看是否可以找出错误,并收到以下结果。

==8641== Warning: silly arg (-501426814648844128) to malloc() 
==8641== Invalid write of size 1 
==8641== at 0x4C2B20D: mempcpy (mc_replace_strmem.c:956) 
==8641== by 0x4EA2F15: _IO_file_xsgetn (fileops.c:1423) 
==8641== by 0x4E971D2: fread (iofread.c:44) 
==8641== by 0x40086D: main (runstats.c:28) 
==8641== Address 0x0 is not stack'd, malloc'd or (recently) free'd 

这是我曾经写过一个使用指针的第一个程序,我茫然为什么它会在一个系统上工作,而不是其他。

+0

加在文件指针的测试和fopen()函数是成功的。 Valgrind表示当我将内存分配给数据时发生错误。我在数据上执行的检查在服务器上失败,但通过我自己的计算机。 – dwv5009 2012-02-03 08:29:36

+0

当我看到这个问题时,首先看到的是:“为什么他在C语言中做这个时,有几十种更合适的语言?” – vines 2012-02-03 08:35:31

回答

5

sizeof(size_t)是平台相关。在OSX上使用默认的32位代码,size_t是4个字节。在64位Linux上,size_t是8个字节。如果您在64位Linux上运行,则您正在读取的是您在32位OSX上阅读的其他n

如果您必须使用二进制数据格式,请不要使用平台特定类型的大小作为字段大小。决定文件头是否是4或8字节,小或大端,并一致使用。

参见: What's sizeof(size_t) on 32-bit vs the various 64-bit data models?

+0

啊!当然。那解决了那个错误。谢谢! 现在我从Valgrind得到的错误是: “未初始化值是由堆栈分配创建的”指向我的主要声明。 – dwv5009 2012-02-03 08:57:40

+0

您是否正在用'fread'读入'size_t'?如果您读取4个字节,请考虑从'stdint.h'将'fread'使用到'uint32_t'中。 – 2012-02-03 09:04:41

2

你绝对应该源发布之前格式化...

使用调试器或执行fread(&n, sizeof(size_t),1,fp);后printf的n的值。似乎你没有得到你所期望的价值。

+0

抱歉格式化,我一定会在将来做。 我已经检查过,n = 20,如预期。 – dwv5009 2012-02-03 08:22:48

+0

@ dwv5009 Valgrind说不是,假设你发布的代码是一个valgrind抱怨的。你是否在调用fread(&n,sizeof(size_t),1,fp)之后检查n = 20,通过添加'printf(“n =%zu \ n”,n) – nos 2012-02-03 08:56:33

+0

@nos是的,我做到了。结果是“n = 20”。 下面的答案解决了它 - 输入文件是在32位系统(4字节)上使用size_t写入的,当我尝试读入64位系统size_t时,输入文件的大小不正确。 – dwv5009 2012-02-03 09:05:16