【问题标题】:Valgrind and strlen() function bugValgrind 和 strlen() 函数错误
【发布时间】:2015-01-24 11:15:38
【问题描述】:

我有一些考试计划。考试系统与 valgrind 配合使用。

请帮帮我 我在 valgrind 中有一些错误,我不知道如何解决我的程序中的错误: 我想将标准输入复制到 *in 指针并从标准输入中删除所有空格和换行符

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define DELTA 2
unsigned int my_strlen(char *str);
char *get_expression(void);
int main(void)
{
    char *in, *out;
    in = get_expression();
    if (!in) {
        return 1;
    }
    out = calloc(my_strlen(in), 1);
    free(out);
    free(in);
    return 0;
}
char *get_expression(void)
{
    char *in, *in_bckp, t;
    in = malloc(DELTA);
    if (!in) {
        return NULL;
    }
    int i, c;
    for (i = 0, c = DELTA; (t = getchar()) != EOF; i++) {
        if (i >= c) {
            in_bckp = in;
            in = realloc(in, c + DELTA);
            if (!in) {
                free(in_bckp);
                return NULL;
            }
            c += DELTA;
        }
        if (c == ' ' || c == '\n') { // i need to remove all of the spaces or newlines
            continue;
        }
        in[i] = t;
    }
    if (i >= c) {
        in_bckp = in;
        in = realloc(in, c + DELTA);
        if (!in) {
            free(in_bckp);
            return NULL;
        }
    }
    in[i] = '\0';
    return in;
}

unsigned int my_strlen(char *str)
{
    unsigned int i;
    for (i = 0; str[i] != '\0' && i < 40000; i++);
    return i;
}

还有我来自 valgrind 的错误:

ivr@debian:/tmp
$ valgrind --leak-check=full --track-origins=yes ./a.out < ~/work/programming/kursovik/parsing/test/data
==5044== Memcheck, a memory error detector
==5044== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==5044== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==5044== Command: ./a.out
==5044== 
==5044== Conditional jump or move depends on uninitialised value(s)
==5044==    at 0x4007D5: my_strlen (test.c:59)
==5044==    by 0x400666: main (test.c:16)
==5044== 
==5044== 
==5044== HEAP SUMMARY:
==5044==     in use at exit: 0 bytes in 0 blocks
==5044==   total heap usage: 17 allocs, 17 frees, 280 bytes allocated
==5044== 
==5044== All heap blocks were freed -- no leaks are possible
==5044== 
==5044== For counts of detected and suppressed errors, rerun with: -v
==5044== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)

请帮我解决这个错误。

【问题讨论】:

  • 第一个使用符号编译(选项-g 用于 gcc)以使 Valgrind 能够精确地引用源代码。第二次使用选项--track-origins=yes 运行 Valgring 以指出未初始化值的来源。
  • 您是否按照 Valgrind 的建议使用 --track-origins=yes 重新运行该作业?这应该会给你一个很好的提示。
  • 但是,在分配和初始化 in 时,您似乎没有注意 0-termination 以使 char-array 成为有效的 C-“字符串”。
  • if (c == ' ' || c == '\n') -- 这里,c 是您的分配大小。那应该是t,这是getchar() 的结果。请选择有意义的名称。
  • 是的,谢谢,但 valgrind 检测到错误

标签: c memory-leaks valgrind


【解决方案1】:

您在in 数组中留下了空白。基本上,你说:

int i, t;

for (i = 0; (t = getchar()) != EOF; i++) {
    if (t == ' ' || t == '\n') continue;
    in[i] = t;
}

当您读取空格或换行符时,您会跳过赋值,但会增加 i++。 Valgrind(正确地)将in 中的这些空白识别为单元化内存。

for 循环在这里不是一个好的选择。 while 循环可能会更好:

int t;
int i = 0;

while ((t = getchar()) != EOF) {
    if (t != ' ' && t != '\n') in[i++] = t;
}

注意计数器i 是如何仅在分配发生时递增的。这两个密切相关的事件几乎同时进行。

【讨论】:

  • 我需要删除所有的空格和换行符。
  • 而我展示的代码没有做到这一点? (代码只是循环的核心,没有动态分配。)
  • 将 (c != ' ' && c != '\n') 更改为 (t != ' ' && t != '\n')
  • 好的,已更正。 (我从上面复制了你的错误,我曾警告你不要使用好的变量名。哦,好吧。)
  • 是的,我认为 t = temp,c = count,但名字很糟糕
猜你喜欢
  • 2011-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多