Указатель на ФАЙЛ обнуляет себя, не будучи использованным вообще - PullRequest
0 голосов
/ 04 октября 2010

в следующем коде при запуске приведет к ошибке сегментации из-за передачи FILE * в fclose, который не содержит адреса (NULL) Мне интересно, почему это происходит, ФАЙЛ * не используется, что так закончилось. ФАЙЛ * называется urandom и передается в fclose в основной функции.

Спасибо

#include <stdio.h>
#include <stdlib.h>

struct property
{
    char *name;
    unsigned int value;
    unsigned int owner;
    unsigned int type;
};

struct player
{
    unsigned int id;
    unsigned int money;
    unsigned int position;
};

int rollDice(FILE *);
int amountOfLines(FILE *);
int createArrayOfPtrs(int ,void ***);
int makeArryOfPropertyPtrs(int ,struct property **);
int FillArryPropertyData(struct property **,int ,FILE *);
int splitBuffer(char *,unsigned int *,char **);
int bufferPropertyFile(FILE *,char **,int );
i    nt fillPropertyStruct(struct property *,unsigned int ,char *);

int main(void)
{   
    int linesInPropertyFile = 0;
    struct property **arrayForProperties = 0;

    //Open /dev/urandom for rollDice
    FILE *urandom = fopen("/dev/urandom","rb");
    FILE *propertyFile = fopen("/home/jordan/Documents/Programming/Monopoly Project/properties","rb");
    if(propertyFile == NULL || urandom == NULL)
    {
        puts("ERROR: error in opening file(s)");
        return 1;
    }
    linesInPropertyFile = amountOfLines(propertyFile);
    //DEBUG
    printf("%d is contained within \"linesInPropertyFile\"\n",linesInPropertyFile);

    if(createArrayOfPtrs(linesInPropertyFile,(void ***)&arrayForProperties))
    {
        puts("ERROR: error from createArrayOfPointers()");
        return 1;
    }
    //DEBUG
    printf("Outside Pointer: %p\n",arrayForProperties);

    if(makeArryOfPropertyPtrs(linesInPropertyFile,arrayForProperties))
    {
        puts("ERROR: error from createArrayOfPointersForProperties()");
        return 1;
    }
    if(FillArryPropertyData(arrayForProperties,linesInPropertyFile,propertyFile))
    {
        puts("ERROR: error from FillArryPropertyData()");
    }

    //Close FILE stream for /dev/urandom
    fclose(urandom);
    fclose(propertyFile);
    return 0;
}

int FillArryPropertyData(struct property **array,int amntOfProperties,FILE *fp)
{
    int bufferUsed = 100;
    int i = 0;
    int returnValue = 0;
    int returnValue2 = 0;
    unsigned int money = 0;
    char *name;
    char *buffer;

    rewind(fp);

    while(returnValue == 0)
    {
        buffer = malloc(bufferUsed);
        returnValue = bufferPropertyFile(fp,&buffer,bufferUsed);
        if(returnValue && returnValue != -1)
        {
            puts("ERROR: error from bufferPropertyFile()");
            return -1;
        }       
        if(returnValue == -1)
        {
            break;
        }
        if(buffer[0] != '\0')
        {
            returnValue2 = splitBuffer(buffer,&money,&name);
        }
        if(returnValue2)
        {
            puts("ERROR: error in splitBuffer()");
            return 1;
        }
        if(fillPropertyStruct(array[i],money,name))
        {
            puts("ERROR: error in fillPropertyStruct()");
            return 1;
        }
        money = 0;
        i++;
    }
    free(buffer);

    return 0;
}

int fillPropertyStruct(struct property *array,unsigned int money,char *name)
{
    int nameSize = 100;
    int i = 0;
    array->name = malloc(nameSize);
    array->value = money;
    while(1)
    {
        if(i >= nameSize)
        {
            void *tmp = realloc(array->name,nameSize * 2);
            nameSize *= 2;
            if(tmp)
            {
                array->name = tmp;
            }
            else
            {
                return -1;
            }
        }
        if(name[i] == '\0')
        {
            break;
        }
        array->name[i] = name[i];
        i++;
    }
    array->name[i] = '\0';

    return 0;
}
int splitBuffer(char *buffer,unsigned int *money,char **name)
{
    int i = 0;
    int j = 1;
    int nameSize = 100;

    *name = malloc(nameSize);
    while(1)
    {
        if(buffer[j] != '"')
        {
            (*name)[j-1] = buffer[j];
        }
        else
        {
            i++;
        }
        j++;
        if(i)
        {
            break;
        }
        if(j >= nameSize)
        {
            void *tmp = 0;
            tmp = realloc(*name,nameSize * 2);
            nameSize = nameSize * 2;
            if(tmp != NULL)
            {
                *name = tmp;
            }
            else
            {
                puts("ERROR: error in splitBuffer");
                return -1;
            }
        }
    }
    name[j-1] = '\0';

    while(buffer[j] != '$')
    {
        if(buffer[j] == '\0')
        {
                puts("ERROR: error in splitBuffer()");
            return -2;
        }
        j++;
    }
    j++;
    while(buffer[j] != '\0')
    {
        *money += (buffer[j] - '0');
        if(buffer[j+1] != '\0')
        {
            *money *= 10;
        }
        j++;
    }
    printf("BUFFER: %s\n",buffer);
    printf("NAME: %s\n",*name);
    printf("MONEY: %d\n",*money);
    return 0;
}

int bufferPropertyFile(FILE *fp,char **buffer,int i)
{   
    int j = (i - i);

    if(feof(fp))
    {
        //-1 Returned if EOF detected
        return -1;
    }
    char retr = 0;
    while(1)
    {
        if(j + 1 >= i)
        {
            void *tmp = realloc(*buffer,i * 2);
            if(tmp != NULL)
            {
                *buffer = tmp;
                i = i * 2;
            }
            else
            {
                puts("ERROR: error in bufferPropertyFile()");
                return -2;
            }
        }
        retr = fgetc(fp);
        if(retr == '\n' || feof(fp))
        {
            break;
        }
        (*buffer)[j] = retr;
        j++;
    }
    (*buffer)[j] = '\0';
    if(**buffer == '\0')
    {
        return -1;
    }
    return 0;
}




int rollDice(FILE *fp)
{
    int seed = fgetc(fp);
    srand(seed);
    return (rand() % 6) + 1;
}

int amountOfLines(FILE *file)
{
    int i = 0;
    int retr = 0;

    while(1)
    {
        retr = fgetc(file);
        if(retr == EOF)
        {
            break;
        }
        if(retr == '\n' )
        {
            i++;
        }
    }
    return i;
}
int createArrayOfPtrs(int numberOfPointers,void ***pointer)
{
    void *tmp = malloc(numberOfPointers * sizeof (tmp));
    if(tmp != NULL)
    {
        *pointer = tmp;
        //DEBUG
        printf("Pointer: %p\n",*pointer);
    }
    else
    {
        return 1;
    }
    return 0;
}

int makeArryOfPropertyPtrs(int numberOfPointers,struct property **pointer)
{
    int i = 0;
    void *tmp;
    for(i = 0;i < numberOfPointers;i++)
    {
        tmp = malloc(sizeof(struct property));
        if(tmp == NULL)
        {
            return 1;
        }
        pointer[i] = (struct property *)tmp;
    }
    return 0;
}

Ответы [ 2 ]

2 голосов
/ 04 октября 2010

здесь это дает нарушение прав доступа в splitBuffer на этой строке:

name[j-1]='\0';

что, вероятно, должно быть

(*name)[j-1]='\0';

на самом деле, память нигде не выделяется, другими словами, неопределенное поведение, которое действительно в вашем случае может перезаписать переменную urandom: и urandom, и name размещаются в стеке, поэтому в зависимости от значения j он может записывать поверх urandom ..

кроме этого, может быть больше ошибок, количество и использование указателей / mallocs / reallocs, а отсутствие освобождений немного страшно

1 голос
/ 04 октября 2010
int createArrayOfPtrs(int ,void ***);

if(createArrayOfPtrs(linesInPropertyFile,(void ***)&arrayForProperties))

Это неопределенное поведение, (void***) не совместимо с (struct property ***). Почему вы даже используете это здесь, все остальные функции используют указатели свойств структуры?

Поскольку массив расположен прямо перед указателем файла в локальных переменных main, возможно, проблема в том, что создание / инициализация массива перезаписывает urandom?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...