Ошибка выделения памяти - в Linux, но не в OSX Unix - PullRequest
0 голосов
/ 03 февраля 2012

Я пишу код для пакета статистики и начинаю с чтения данных в массив указателей. Я инициализирую указатель и выделяю достаточно памяти, используя malloc; однако иногда я получаю ошибку в распределении памяти в конце кода ниже.

#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

Это первая из написанных мною программ, в которых используются указатели, и я не знаю, почему она будет работать в одной системе, а в другой - нет.

Ответы [ 2 ]

5 голосов
/ 03 февраля 2012

sizeof(size_t) зависит от платформы.В OSX с 32-битным кодом по умолчанию size_t составляет 4 байта.В 64-битном Linux size_t составляет 8 байтов.Если вы работаете в 64-битной Linux, вы читаете другую n, которую вы читаете в 32-битной OSX.

Если вы должны использовать двоичный формат данных, не используйте размерплатформо-зависимых типов в качестве размера поля.Решите, будет ли заголовок файла 4 или 8 байтов, с прямым или младшим порядком байтов, и используйте его последовательно.

См .: Что такое sizeof (size_t) в 32-битных по сравнению с различными 64-битными моделями данных?

2 голосов
/ 03 февраля 2012

Вы обязательно должны отформатировать свой источник перед публикацией ...

Используйте отладчик или напечатайте значение n после выполнения fread(&n, sizeof(size_t),1,fp);.Кажется, вы не получили ожидаемое значение.

...