【问题标题】:Loss of values in array in struct after function execution函数执行后结构中数组中的值丢失
【发布时间】:2014-09-03 12:21:57
【问题描述】:

我正在编写一个 c 代码,该代码包含一个包含一些值的结构,我称之为范围。

我的目的是动态使用这个所谓的范围(在每次执行时保存不同数量的数据)。我现在暂时使用 #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;
}

【问题讨论】:

标签: c arrays struct malloc loss


【解决方案1】:

您的 copy_range 函数已损坏,因为它仅复制指向大小和值的指针,而不是内存。在您调用 free(range.size);free(range.values); 之后,您也在从原始对象中删除 mamory,但没有将其指针设置回 NULL。

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

【讨论】:

  • 感谢您的有用解释。我现在正在实施 uesp 的解决方案。对于更新函数的范围,我没有将其指针设置回 NULL 吗?我以为我做到了。另一方面,我实际上并不想让 s1.range 指向 NULL,而是更新/设置。
【解决方案2】:

由于访问已释放的内存,您遇到了未定义的行为 (UB)。您的 copy_range() 函数仅对两个指针字段进行浅拷贝,因此当您运行 free(range-&gt;size) 时,您会使 arg-&gt;range-&gt;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));

【讨论】:

  • 谢谢你的建议,uesp。实际上,j123b567 的解释也很有用。我想知道我是否仍然可以使用建议的深拷贝,同时 free(range.size);范围.size=NULL;免费(范围。值); range.values=NULL;像我以前那样在 update_range 函数中。
  • 在这种情况下,你应该释放它们。
【解决方案3】:
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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-03
    • 1970-01-01
    • 2018-12-26
    • 2017-02-02
    • 2021-04-26
    • 2012-05-06
    • 2021-08-17
    相关资源
    最近更新 更多