2014-09-03 72 views
0

我正在研究一个包含一些结构的c代码,该结构承载了一些我称之为范围的值。函数执行后struct中数组中值的丢失

我的目的是动态地使用这个所谓的范围(每次执行时都保持不同数量的数据)。我现在暂时使用#define comp。每当我通过使用s1结构(和内存分配)调用update_range时,这个所谓的范围就会得到更新。

我发现奇怪的是,当我引入一个“show_range”函数来输出更新函数内部/外部的实际值时,我意识到我松开了前两个值。 这是代码。 对此有何建议? 在此先感谢!

#include <stdio.h> 
#include <stdlib.h> 
#include <stdbool.h> 
#include <errno.h> 
#include <string.h> 
#include <complex.h> 
#define comp 1024 

// struct holding a complex-valued range 
struct range { 
    int dimensions;   /* number of dimensions */ 
    int* size;    /* array holding number of points per dimension */ 
    complex double* values; /* array holding complex valued */ 
    int components; /* number of components that will change on any execution*/ 
}; 

// parameters to use in function 
struct s1 { 
    int tag; 
    struct range* range; 
}; 

int update_range(struct s1* arg); 
int show_range(struct range* argrange, char* message); 
int copy_range(struct range* in, struct range* out); 

int main(void) { 
    int ret = 0; 
    struct s1 s1; 
    s1.tag = 0; 
    s1.range = malloc(sizeof(struct range)); 
    update_range(&s1); 
    show_range(s1.range, "s1.range inside main function"); 

    return ret; 
} 

//////////////////////////////////////////// 
int update_range(struct s1* arg) { 
    int ret = 0; 
    int i; 
    struct range range; 
    range.dimensions = 1; 
    range.size = malloc(range.dimensions * sizeof(int)); 
    range.components = comp; 
    range.size[0] = range.components; // unidimensional case 
    range.values = malloc(range.components * sizeof(complex double)); 
    for (i = 0; i < range.components; i++) { 
     range.values[i] = (i + 1) + I * (i + 1); 
    } 
    show_range(&range, "range inside update_range function"); 

    arg->range->size = 
     malloc(range.dimensions * sizeof(int)); // size was unknown before 
    arg->range->values = 
     malloc(comp * sizeof(complex double)); // amount of values was unknown 
    copy_range(&range, arg->range); 
    show_range(arg->range, "arg->range inside update_range function"); 

    if (range.size) 
     free(range.size); 
    range.size = NULL; 
    if (range.values) 
     free(range.values); 
    range.values = NULL; 
    return ret; 
} 

//////////////////////////////////////////// 
// Show parameters (10 first values) 
int show_range(struct range* argrange, char* message) { 
    int ret = 0; 
    vint i; 
    printf(" ******************************\n"); 
    printf(" range in %s \n", message); 
    printf(" arg.dimensions=%d \n", argrange->dimensions); 
    printf(" arg.size[0]=%d \n", argrange->size[0]); 
    printf(" argrange.components=%d \n", argrange->components); 
    printf("  first 10 {Re} values: \n"); 
    for (i = 0; i < 10; i++) { 
     printf(" argrange.values[%d]=%f\n", i, creal(argrange->values[i])); 
    } 
    printf("\n"); 
    return ret; 
} 

//////////////////////////////////////////// 
// copy range 
int copy_range(struct range* in, struct range* out) { 
    int ret = 0; 

    if (in == NULL) { 
     fprintf(stderr, "error: in points to NULL (%s:%d)\n", __FILE__, 
       __LINE__); 
     ret = -1; 
     goto cleanup; 
    } 
    if (out == NULL) { 
     fprintf(stderr, "error: out points to NULL (%s:%d)\n", __FILE__, 
       __LINE__); 
     ret = -1; 
     goto cleanup; 
    } 

    out->dimensions = in->dimensions; 
    out->size = in->size; 
    out->values = in->values; 
    out->components = in->components; 

cleanup: 
    return ret; 
} 
+0

https://stackoverflow.com/help/mcve – chrk 2014-09-03 12:25:52

回答

0

由于访问释放的内存,您正在遇到未定义的行为(UB)。您的copy_range()函数只会执行两个指针字段的浅表副本,因此当您运行free(range->size)时,表明arg->range->size无效。

你应该通过分配和复制指针内容像做copy_range()深层副本:

out->size = malloc(in->dimensions * sizeof(int)); 
memcpy(out->size, in->size, in->dimensions * sizeof(int)); 

out->values = malloc(in->components * sizeof(complex double)); 
memcpy(out->values , in->values, in->components * sizeof(complex double)); 
+0

谢谢你的建议,uesp。其实j123b567的解释也很有用。我想知道我是否仍然可以使用建议的深层副本,同时可以使用free(range.size); range.size = NULL;自由(range.values); range.values = NULL;像我以前那样在update_range函数内部。 – mae 2014-09-03 12:56:11

+0

在这种情况下,你应该释放它们。 – j123b567 2014-09-03 13:10:56

1

您的copy_range函数被破坏,因为它只复制指向大小和值的指针而不是内存。在您致电free(range.size);free(range.values);之后,您将从原始对象中删除内存,但不会将其指针设置回NULL。

调用update_range之后,s1.range具有非空指针的大小和值,但它们指向已删除的内存。

+0

感谢您的有用的解释。我现在正在实施uesp的解决方案。我是不是在更新函数中将其指针设置回NULL?我以为我做到了。另一方面,我并不想让s1.range指向NULL但更新/设置。 – mae 2014-09-03 13:04:32

0
There are not 10 items to print, so the lines: 

printf("  first 10 {Re} values: \n"); 
for (i = 0; i < 10; i++) { 
    printf(" argrange.values[%d]=%f\n", i, creal(argrange->values[i])); 
} 

Will be printing from random memory. 
a much better method would be: 

    printf("  first %d {Re} values: \n", min(argrange.components,10)); 
for (i = 0; i < argrange.components; i++) { 
    printf(" argrange.values[%d]=%f\n", i, creal(argrange->values[i])); 
} 

The above is just one of many problems with the code. 
I would suggest executing the code using a debugger to get the full story. 
as it is, the code has some massive memory leaks due mostly 
to overlaying malloc'd memory pointers. 
for instance as in the following: 

arg->range->size = 
    malloc(range.dimensions * sizeof(int)); // size was unknown before 
arg->range->values = 
    malloc(comp * sizeof(complex double)); // amount of values was unknown