我正在使用Valgrind在小应用程序的C代码上运行内存分析,它使用DFS方法找出图中的所有路径。但我仍然遇到一些错误,主要是在这部分代码中:
public static IEnumerable<T> InsertInOrder<T>(
this IEnumerable<T> source,
T insertion) where T : IComparable<T>
{
using (var e = source.GetEnumerator())
{
while (e.MoveNext())
{
if (e.Current.CompareTo(insertion) < 0)
{
yield return e.Current;
}
else
{
yield return insertion;
yield return e.Current;
goto continueEnumerating;
}
}
yield return insertion;
goto exit;
continueEnumerating:
while (e.MoveNext())
{
yield return e.Current;
}
exit:
yield break;
}
我得到了这些valgrind错误:
int process_edges(VoidStack *edges, char *buffer)
{
char weight[DATE_LENGTH] = "";
char min_weight[DATE_LENGTH] = "", max_weight[DATE_LENGTH] = "";
int metric;
VoidStack *reverse = malloc(sizeof(VoidStack));
void_stack_new(reverse, DATE_LENGTH);
/* Create reverse stack to have edges in correct order */
while (edges->loglength != 0)
{
void_stack_pop(edges, weight);
void_stack_push(reverse, weight);
}
if (reverse->loglength >= 1)
{
void_stack_pop(reverse, weight);
strcpy(max_weight, weight);
strcpy(min_weight, weight);
sprintf(buffer + strlen(buffer), "%s", weight);
void_stack_push(edges, weight);
}
我不知道如何修复这些错误。
我正在使用这些参数运行Valgrind
- leak-check = full --track-originins = yes --show-reachable = yes
整个代码位于https://github.com/AdamPalaxo/KIV-PC。
编辑:
添加了==1399== Conditional jump or move depends on uninitialised value(s)
==1399== at 0x4C2C2AB: strcpy (vg_replace_strmem.c:458)
==1399== by 0x4010D5: process_edges (in /home/adam/C/dfs.out)
==1399== by 0x401508: dfs (in /home/adam/C/dfs.out)
==1399== by 0x4015A9: dfs (in /home/adam/C/dfs.out)
==1399== by 0x40172A: all_paths (in /home/adam/C/dfs.out)
==1399== by 0x401AEC: main (in /home/adam/C/dfs.out)
==1399== Uninitialised value was created by a stack allocation
==1399== at 0x40100D: process_edges (in /home/adam/C/dfs.out)
==1399==
==1399== Conditional jump or move depends on uninitialised value(s)
==1399== at 0x4C2C2AB: strcpy (vg_replace_strmem.c:458)
==1399== by 0x4010E8: process_edges (in /home/adam/C/dfs.out)
==1399== by 0x401508: dfs (in /home/adam/C/dfs.out)
==1399== by 0x4015A9: dfs (in /home/adam/C/dfs.out)
==1399== by 0x40172A: all_paths (in /home/adam/C/dfs.out)
==1399== by 0x401AEC: main (in /home/adam/C/dfs.out)
==1399== Uninitialised value was created by a stack allocation
==1399== at 0x40100D: process_edges (in /home/adam/C/dfs.out)
,void_stack_new
和void_stack_push
函数的代码。
void_stack_pop
答案 0 :(得分:0)
OP在评论中发布了这个
好的,谢谢。我还添加了初始化堆栈的函数
void_stack_new
。 值s->element_size
保持11,因为输入数据的格式为YYYY-MM-DD
加上我 考虑\0
终止字节。所以堆栈总是期望输入 总是大小相同。
我想,我解决了这个问题。我用你的堆栈代码自己做了一些测试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct stack {
int element_size;
int loglength;
int allocated_length;
void *elements;
} VoidStack;
// I did copy & paste of your posted code
// not showing it here because it makes the code
// too long
void void_stack_print(VoidStack *s)
{
char el[11];
printf("Void Stack, element size: %d, #elements: %d, max #elements: %d\n",
s->element_size, s->loglength, s->allocated_length);
printf("Elements as strings:\n");
for(int i = 0; i < s->loglength; ++i)
{
memcpy(el, ((char*) s->elements) + s->element_size * i, s->element_size);
printf(" - %s\n", el);
}
puts("");
}
int main(void)
{
VoidStack stack;
void_stack_new(&stack, 11);
void_stack_push(&stack, "2012-01-01");
void_stack_push(&stack, "2012-01-02");
void_stack_push(&stack, "2012-01-03");
void_stack_push(&stack, "2012-01-04");
void_stack_print(&stack);
void_stack_push(&stack, "2013-01-01");
void_stack_push(&stack, "2013-01-02");
void_stack_print(&stack);
char date[11], copy[11];
void_stack_pop(&stack, date);
strcpy(copy, date);
printf("date: %s, copy: %s\n", date, copy);
void_stack_print(&stack);
void_stack_pop(&stack, date);
strcpy(copy, date);
printf("date: %s, copy: %s\n", date, copy);
void_stack_print(&stack);
free(stack.elements);
return 0;
}
我的valgrind告诉我这个:
==748== Memcheck, a memory error detector
==748== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==748== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==748== Command: ./a
==748==
Void Stack, element size: 11, #elements: 4, max #elements: 4
Elements as strings:
- 2012-01-01
- 2012-01-02
- 2012-01-03
- 2012-01-04
Void Stack, element size: 11, #elements: 6, max #elements: 8
Elements as strings:
- 2012-01-01
- 2012-01-02
- 2012-01-03
- 2012-01-04
- 2013-01-01
- 2013-01-02
date: 2013-01-02, copy: 2013-01-02
Void Stack, element size: 11, #elements: 5, max #elements: 8
Elements as strings:
- 2012-01-01
- 2012-01-02
- 2012-01-03
- 2012-01-04
- 2013-01-01
date: 2013-01-01
date: 2013-01-01, copy: 2013-01-01
Void Stack, element size: 11, #elements: 4, max #elements: 8
Elements as strings:
- 2012-01-01
- 2012-01-02
- 2012-01-03
- 2012-01-04
==748==
==748== HEAP SUMMARY:
==748== in use at exit: 0 bytes in 0 blocks
==748== total heap usage: 3 allocs, 3 frees, 1,156 bytes allocated
==748==
==748== All heap blocks were freed -- no leaks are possible
==748==
==748== For counts of detected and suppressed errors, rerun with: -v
==748== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
但是,如果我将数据更改为推送
void_stack_print(&stack);
void_stack_push(&stack, "2013-01-01XXXXXXX"); // <--- see here
void_stack_push(&stack, "2013-01-02");
void_stack_print(&stack);
char date[11], copy[11];
void_stack_pop(&stack, date);
strcpy(copy, date);
printf("date: %s, copy: %s\n", date, copy);
void_stack_print(&stack);
void_stack_pop(&stack, date);
strcpy(copy, date);
printf("date: %s, copy: %s\n", date, copy);
void_stack_print(&stack);
看看会发生什么:
date: 2013-01-02, copy: 2013-01-02
Void Stack, element size: 11, #elements: 5, max #elements: 8
Elements as strings:
- 2012-01-01
- 2012-01-02
- 2012-01-03
- 2012-01-04
- 2013-01-01X
==813== Invalid write of size 1
==813== at 0x4C2E1D8: strcpy (vg_replace_strmem.c:510)
==813== by 0x108C50: main (a.c:92)
==813== Address 0x1fff001000 is not stack'd, malloc'd or (recently) free'd
==813==
==813==
==813== Process terminating with default action of signal 11 (SIGSEGV)
==813== Access not within mapped region at address 0x1FFF001000
==813== at 0x4C2E1D8: strcpy (vg_replace_strmem.c:510)
==813== by 0x108C50: main (a.c:92)
==813== If you believe this happened as a result of a stack
==813== overflow in your program's main thread (unlikely but
==813== possible), you can try to increase the size of the
==813== main thread stack using the --main-stacksize= flag.
==813== The main thread stack size used in this run was 8388608.
==813==
==813== HEAP SUMMARY:
==813== in use at exit: 88 bytes in 1 blocks
==813== total heap usage: 3 allocs, 2 frees, 1,156 bytes allocated
==813==
==813== LEAK SUMMARY:
==813== definitely lost: 0 bytes in 0 blocks
==813== indirectly lost: 0 bytes in 0 blocks
==813== possibly lost: 0 bytes in 0 blocks
==813== still reachable: 88 bytes in 1 blocks
==813== suppressed: 0 bytes in 0 blocks
==813== Rerun with --leak-check=full to see details of leaked memory
==813==
==813== For counts of detected and suppressed errors, rerun with: -v
==813== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault
我得到了一个非常类似的错误,但我认为这解决了这个问题。
您的push
和pop
方法没有错误,它们会复制正确的数量
字节。问题是"2013-01-01XXXXXXXX"
长于11个字符,
push
复制了11个字符,但没有'\0'
终止字节
在这11个字节中。 strcpy
但需要有效'\0'
- 终止
字符串,但如果找不到,则错误。
我在评论中告诉你了
如果是字符串(例如
weight
),你在考虑\0
终止字节吗? 真的是所有相同长度的字符串(您的堆栈期望输入始终具有相同的大小)吗?
我不是那么遥远,一个问题可能是DATE_LENGTH
不够大,或者
由于某种原因,你推动的字符串长度超过11个字符。无论如何,你需要
确保不要推送任何大于10个字符的字符串。你的堆栈不知道
字符串和字符串长度,无论类型如何,它总是复制element_size
个字节,
所以push
方法的调用者有责任确保
没有字符串长度超过10个字符。
在执行初始推送之前使用调试器或添加printf
并检查每一个
你推的字符串不超过10个字符。