简体   繁体   中英

Pointer array contents wiped when passed to a function in C

so I am loading lines of floats from text files and storing them in a pointer array, before saving them back to a text file and adding a reference to their size. The number of values in the text file varies so the array must be dynamic. I define my pointer array in main like this.

size_t size = (int)100 * sizeof(float);
float * val = malloc(size);

I then pass the pointer array to a function that loads the text file and saves the values to it, like this.

//Read file into array.
int readFile(float *val, int size) {

char buf[20] = { 0 };
val[0] = 0;
double temp = 0;
int i = 1;
FILE *file;
file = fopen("C:\\Users\\MoldOffice\\Dropbox\\VS\\finalproj\\ecgproject\\dataStream", "r");
if (!file) {
    printf("Coulding find file.\n");
    exit(1);
}

while (fgets(buf, 20, file) != NULL) {
    temp = atof(buf);
    if (temp != 0) {
        // Increment i to find the size of the useful data.
        val[i] = temp;
        //printf("%d",val[i]);
        i++;
        if (i == size / sizeof(float)) {
            size += 100*sizeof(float);
            double* val_temp = realloc(val, size);
            if (val_temp == NULL) {
                printf("Realloc failed.\n");
            }
            else {
                val = val_temp;
            }
        }
    }
}
//Test that the array is readable.
for (int i = 0; i < 5; i++) printf("val[%d]=%f\n", i, val[i]);

return(i);
fclose(file);

This works fine and when I print the contents of the pointer array back in main, it works. I then pass the same pointer array to another function which saves the array in a new text file, along with the size on the first line, the problem is that when I pass the pointer array for a second time, the contents have changed (mostly 0 with some random numbers). I have absolutely no idea why this is happening.. Any ideas? The function that writes the file is here:

// Write file into array.
void writeFile(float *val,int size) {

printf("%d",sizeof(val));
FILE *file;
int sampleNum;
char buf[10];
file = fopen("sampleNum.txt", "r");
if (file == NULL) { sampleNum = 0; }
else { fscanf(file, "%d", &sampleNum); printf("%d",sampleNum);}
char fileString[10];
sprintf(fileString,"sample%d\0", sampleNum);
file = fopen(fileString, "w");

//Test that the array is readable.
for (int i = 0; i < 5; i++) printf("val[%d]=%f\n", i, val[i]);

//Print the array to a text file and save.
fprintf(file, "%d\n", size);
for (int i = 1; i < size; i++) {
    fprintf(file, "%f\n", val[i]); 
    printf("%f\n", val[i]); }
fclose(file);
}

The rest of main can be found here:

int main() {

size_t size = (int)100 * sizeof(float);
float * val = malloc(size);

// Read the data into an array.
int arraySize = readFile(val, size);

//Test that the array is readable.
for (int i = 0; i < 5; i++) printf("val[%d]=%f\n", i, val[i]);

// Save the array to a text file, with the size of the array as the first element.
writeFile(val,arraySize);

}
        double* val_temp = realloc(val, size);
        if (val_temp == NULL) {
            printf("Realloc failed.\n");
        }
        else {
            val = val_temp;

The caller of this function has no way to know that you've moved the array to a different place. It's still got the old, now invalid, pointer.

You have a similar problem with size . How does the caller know you changed it?

You choice of division of responsibilities is poor. If the caller is responsible for allocating the buffer, then this function should ask the caller to enlarge it. If this function is responsible for allocating the buffer, it should allocate it. It's generally a very bad idea to split up the responsibility for managing the allocation of a chunk of memory, and this shows one of the reasons why.

Perhaps pass in a pointer to a structure that contains a pointer to a buffer and its size? That will work, but still shows poor division of responsibilities.

Perhaps have this function allocate the buffer and return a structure that includes a pointer to it and the number of elements in it?

If you really want to to do things this way, consider passing the function a pointer to a structure that includes a pointer to the array, the size of the array, and a pointer to a function that resizes the array. The caller can, of course, set this pointer to point to the realloc function (though it's probably better for it to be a function that changes the pointer and size members of the structure).

You could also use code like this:

struct float_buffer
{
    float* buffer;
    int size;
};

struct float_buffer allocate_float_buffer(int size)
{
    struct float_buffer buf;
    buf.buffer = malloc (size * sizeof(float));
    buf.size = size;
    return buf;
}

bool resize_float_buffer(struct float_buffer* buf, int size)
{
    float* tmp = realloc(buf->buffer, size * sizeof(float));
    if (tmp == NULL)
        return false;
    buf->buffer = tmp;
    buf->size = size;
    return true;
}

And then pass the function a struct float_buffer * .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM