【问题标题】:C code seems to work, but valgrind says an array is not initializedC 代码似乎可以工作,但 valgrind 说数组未初始化
【发布时间】:2014-10-16 05:19:34
【问题描述】:

我目前正在做一个我自己的标记器的项目。我的代码可以编译并且工作正常,但是 valgrind 给出了错误:

==2572== Conditional jump or move depends on uninitialised value(s)
==2572==    at 0x4C2B308: strlen (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==2572==    by 0x400FCB: strdup (Lex1.c:173)
==2572==    by 0x400EBA: lex (Lex1.c:140)
==2572==    by 0x400A3B: main (mainLex.c:34)
==2572== 
==2572== Conditional jump or move depends on uninitialised value(s)
==2572==    at 0x4C2B35B: strcpy (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==2572==    by 0x400FFC: strdup (Lex1.c:177)
==2572==    by 0x400EBA: lex (Lex1.c:140)

lex 中的第 140 行是以下代码中的“temp->text”行:

token *head, *temp, *right, *temp1;
char *line1 = strdup(line);
char *curr = separatebetter(line1);
temp = (token *)malloc(sizeof(token));
temp->text=strdup(curr);

奇怪的是,我可以打印 curr 的值,但根据我的假设,valgrind 表示 curr 在任何时候都没有初始化,尽管我清楚地初始化了它。

valgrind 在 strdup 中引用的两行是:

int n = strlen(str) + 1;
strcpy(dup, str);

而separatebetter的相关代码是:

char *separatebetter (char *arr)
{
    int status=0;
    static char* perm;
    if (arr!=NULL)
    {
        perm=arr;
    }
    if((perm[0]=='\0')||(perm[0]=='\n'))
    {
        return NULL;
    }
    if (strcspn(perm, "<|>&")==0)
    {
        status=1;
    }
    if (strcspn(perm, ";()")==0)
    {
        status=2;
    }
    char *toke = perm;
    char *temp;
    //Status is set to 1 or 2
    if (status==1)
    {
        printf("here\n");
        temp=toke;
        char *temp1=malloc(strlen(temp)*sizeof(char));
        temp1=temp;
        char *final = malloc(3*sizeof(char));
        temp1++;
        if(temp[0]==temp1[0])
        {
            final[0]=temp[0];
            final[1]=temp[0];
            *temp='\0';
            temp++;
            *temp='\0';
            perm=temp+1;
            return final;
        }
        else
        {
            final[0]=temp[0];
            final[1]='\0';
            *temp='\0';
            perm=temp+1;
            return final;
        }
    }
    else if (status==2)
    {
        temp=toke;
        char *final = malloc(2*sizeof(char));
        final[0]=temp[0];
        final[1]='\0';
        *temp='\0';
        perm=temp+1;
        return final;
    }
    perm[0]='\0';
    return toke;
}

编辑:我试过 printf curr,虽然我得到了输出,但 valgrind 仍然告诉我

==6625== Conditional jump or move depends on uninitialised value(s)
==6625==    at 0x4E7AB5B: vfprintf (in /usr/lib64/libc-2.17.so)
==6625==    by 0x4E83CD8: printf (in /usr/lib64/libc-2.17.so)
==6625==    by 0x400EA8: lex (Lex1.c:138)
==6625==    by 0x400A3B: main (mainLex.c:34)

认为 curr 的初始化是问题,我错了吗?

【问题讨论】:

  • 这是错误的:char *curr = malloc(100*sizeof(char)); curr = separatebetter(line1);。您立即泄漏分配的内存并将curr 设置为指向其他地方。 temp1 也会发生同样的事情。
  • 显示您实际测试的代码。为了获得更好的帮助,发布 MCVE。

标签: c token valgrind


【解决方案1】:

这段代码显然是错误的:

char *curr = malloc(100*sizeof(char));
curr = separatebetter(line1);

您分配内存,然后用来自separatebetter() 的值覆盖指向它的唯一指针。那是立即泄漏。也许您打算使用strcpy()

strcpy(curr, separatebetter(line1));

我需要看看 separatebetter() 做了什么——但这不是你的运行代码,因为它不会编译:

if (strcspn(perm, ";()")==0)
{
    status=2;
}
char *toke = perm;
char *temp;
//Status is set to 1 or 2
else if (status==1)

else 不能在那里编译;前面的语句是一个变量声明。这使得很难知道出了什么问题。获得声称正在运行的不可编译代码是非常烦人的。很难知道什么是可以信任的。

不过,您的函数可以在此代码之前返回 NULL — 并且 strdup(NULL) 的行为未定义,strcpy() 在被告知从(或到)NULL 指针复制时的行为也是未定义的。在您确定它不为空之前,您不能使用 separatebetter() 的返回值。

下面的代码也重复了内存泄漏的问题:

{
    printf("here\n");
    temp=toke;
    char *temp1=malloc(strlen(temp)*sizeof(char));
    temp1=temp;

再一次,也许你打算使用strcpy()

    strcpy(temp1, temp);

separatebetter() 的顶部,您有:

static char* perm;
if (arr!=NULL)
{
    perm=arr;
}
if((perm[0]=='\0')||(perm[0]=='\n'))
{
    return NULL;
}
if (strcspn(perm, "<|>&")==0)
{
    status=1;
}
if (strcspn(perm, ";()")==0)
{
    status=2;
}
char *toke = perm;

static char *perm 令人费解。 arr 的分配有时令人费解。 char *toke = perm; 的使用确实令人费解。先前的代码并不总是设置perm,因此有时它会从先前调用分配给它的函数中获得一个指针。该指针可能仍然有效,也可能无效。我认为你需要重新考虑整个separatebetter()

相信你的工具! (特别相信valgrind!)

【讨论】:

  • 我编辑了上面的 curr 初始化,然后尝试 printf curr,valgrind 告诉我 curr 没有初始化。我认为 curr 中的初始化是问题,我错了吗?
  • 您需要修复代码,以便显示可编译的separatebetter() 函数。
  • 抱歉造成混淆,为了简洁起见,我省略了很多单独的更好的代码(例如,在 else if 之前有一个 if)。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-28
  • 2016-04-13
  • 1970-01-01
  • 2013-12-18
  • 1970-01-01
  • 2019-10-03
  • 1970-01-01
相关资源
最近更新 更多