为什么用 Valgrind 执行 C 程序时 bug 消失了?

发布于 2025-01-14 04:53:41 字数 2528 浏览 4 评论 0原文

我在命令函数开始时分配了两个相当大的结构:第一个是数组和单个值的简单结构,第二个有其内部子结构。

之后,我用一些 fill_functions(struct_1) 填充第一个结构,然后使用第一个结构和外部文件中的数据用其他结构填充 struct_2。 从 struct_1 填充的内容 - 可以被视为键数据和键数据的“渲染”。 从文件中填充的是价值数据,即作为结果要收集的目标信息;所有值数据均由键数据字段提取。

最后,我输出 struct_2 中的所有值。

我的代码方案是这样的:

typedef struct struct_1
{
  // a lot of arrays, ints, chars..
} 
STRUCT_1;


typedef struct sub_struct_A
{
  char strings[5][100];
  // arrays, ints, chars..
} 
SUB_A;

typedef struct sub_struct_B
{
  char strings[5][10][10];
  // arrays, ints, chars..
} 
SUB_B;

typedef struct struct_2
{
  SUB_A sub_struct_A[10];
  SUB_B sub_struct_B[100];
} 
STRUCT_2;


main()
{
    // take it as somewhere before a config struct was initialized..
    char input[100]={0};
    // no matter whats inside..
    some_input(input, config);

    STRUCT_1 *s1 = NULL;  
    s1 = (s1 *)malloc(sizeof(STRUCT_1));

    STRUCT_2 *s2 = NULL;  
    s2 = (s2 *)malloc(sizeof(STRUCT_2));
    
    fill_struct_1(input, s1, config);
    fill_struct_2(s1, s2, config);

    output_struct_2(s2, config);

    free(s1); free(s2);
}


void fill_struct_2(STRUCT_1 *s1, STRUCT_2 *s2, CONF_STRUCT config)
{
    fill_keys_data(s1, s2); 
    fill_value_data(s1, s2, config);
}

void fill_value_data(STRUCT_1 *s1, STRUCT_2 *s2, CONF_STRUCT config)
{
    get__tokenized_buffer__from_file();

    extract_values__from_buf_and_s1__by_conf(s1, s2, config);

}

问题是: 当我在 sub-struct_B[0].strings[0][1] 上按顺序输出两个子结构数组中的所有条目时 - 我从 获取数据>sub-struct_A[0].strings[0]。 对于 sub-struct_B[0].some_int_val_X - 我得到值 (757935400),该字段不允许该值,可能的最大值约为 (150)

所有其他输出始终正常。 'sub-struct_B[i]'中的每个(i)都被填充并输出OK。

当我使用 Valgrind 检查问题的踪迹时,问题就消失了。 是的,Valgrind 表示可能丢失:8 个块中的 8,904 字节

但我对这个工具还很陌生,所以这些信息对我来说什么也没有。现在我不知道如何修复这些可能的泄漏;我的代码 - 工作,不是绝对,但很好。也许我的问题出在这个 Valgrind 消息上,我不知道。

每个子结构的填充逻辑都很庞大,带有rand()和内部过滤器和提取器。抱歉,我无法给出这种逻辑的抽象方案。

现在我猜测,也许一些远方指针出了问题。但我无法想象从哪里开始我的搜索。 sub-struct_B 中的所有 99 个条目均正确输出,但只有 [0]-entry 给出了错误的输出。

很少情况下,[0]-entry 甚至给我的不是来自 sub_struct_A 的数据,而是来自其他地方的大量垃圾。

我唯一的猜测是我在某个地方做了错误的指针算术。不是那么大的想法..

任何人都可以给我一些开始的提示吗?

我知道我是一对一地解决我的问题,只是向在 C 指针调试方面特别有经验的人寻求好的建议。

如果这个猜谜游戏不是你们想要的,那么请给我一个简单问题的答案:

怎么可能,Valgrind 是 100% 正确的输出,并且没有 - 损坏? Valgrind 如何在不修复代码的情况下修复程序?

exec 之间的唯一区别是,对于 Valgrind,我使用标志“-g”进行编译,但对于常见用途 - 使用“-o”。

谢谢。

I'm malloc-ing two pretty big structures at the command-function start: first is a plain structure of arrays and single values, second have its inner sub-structures.

After that, I'm filling first structure with some filling_functions(struct_1), and then I fill struct_2 with other, using data from first struct and from external files.
What is filled from struct_1 - can be minded as keys-data and "render" of key-data.
What is filled from files - is value-data, target information to collect as a result; all value-data are extracted by keys-data fields.

Finally, I'm outputting all values from struct_2.

Scheme of my code some kind of that:

typedef struct struct_1
{
  // a lot of arrays, ints, chars..
} 
STRUCT_1;


typedef struct sub_struct_A
{
  char strings[5][100];
  // arrays, ints, chars..
} 
SUB_A;

typedef struct sub_struct_B
{
  char strings[5][10][10];
  // arrays, ints, chars..
} 
SUB_B;

typedef struct struct_2
{
  SUB_A sub_struct_A[10];
  SUB_B sub_struct_B[100];
} 
STRUCT_2;


main()
{
    // take it as somewhere before a config struct was initialized..
    char input[100]={0};
    // no matter whats inside..
    some_input(input, config);

    STRUCT_1 *s1 = NULL;  
    s1 = (s1 *)malloc(sizeof(STRUCT_1));

    STRUCT_2 *s2 = NULL;  
    s2 = (s2 *)malloc(sizeof(STRUCT_2));
    
    fill_struct_1(input, s1, config);
    fill_struct_2(s1, s2, config);

    output_struct_2(s2, config);

    free(s1); free(s2);
}


void fill_struct_2(STRUCT_1 *s1, STRUCT_2 *s2, CONF_STRUCT config)
{
    fill_keys_data(s1, s2); 
    fill_value_data(s1, s2, config);
}

void fill_value_data(STRUCT_1 *s1, STRUCT_2 *s2, CONF_STRUCT config)
{
    get__tokenized_buffer__from_file();

    extract_values__from_buf_and_s1__by_conf(s1, s2, config);

}

The problem is:
When I'm outputting sequentially all entries from arrays of both sub-structs, on the sub-struct_B[0].strings[0][1] -- I get the piece of data from sub-struct_A[0].strings[0].
And for sub-struct_B[0].some_int_val_X -- I get value (757935400), which is not allowed for that field, possible maximum for which is about (150).

All other output is always OK. Each (i) in 'sub-struct_B[i]' is filled and outputted OK.

When I'm using Valgrind to check, what's the trace of my problem, the problem just disappears..
And yes, Valgrind says that there's possibly lost: 8,904 bytes in 8 blocks.

But I'm very new to this tool, so that information gives me just nothing. Now I don't know how to fix these possible leaks; my code - works, not absolutely, but fine. Maybe my problem lies upon this Valgrind message, i don't know.

Filling logic of each sub-struct is huge, with rand()'s and inner filtrations and extractors. I can't give an abstract scheme of this logic, sorry.

Now I'm guessing, maybe something goes wrong with some distant side pointers. But I can't imagine where to start my search. All 99 entries from sub-struct_B are outputted correctly, but only [0]-entry gives me bad output.

Rarely, [0]-entry even gives me not that data from sub_struct_A, but a lot of garbage from other places.

My only guess is that I am doing wrong pointer arithmetics somewhere. Not so big idea..

Can anybody give me some hints to start?

I know that I'm one-on-one with my problem, just seeking for good suggestions from people being experienced specially in C-pointers debugging.

If this guess-game is not what you guys seeking on, than give me an answer on one simple question, please:

How can that be, that with Valgrind -- there is 100% correct output, and without - corrupted? How Valgrind can fix the program without fixing the code??

Only difference between execs, is that for Valgrind I am compiling with flag '-g', but for common use - with '-o'.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文