char** 和 valgrind 条件跳转错误

问题描述 投票:0回答:2

首先我的问题只是C,而不是C++。我已经搜索过 SO 并谷歌我的问题,但我认为这是由于缺乏对 valgrind 和 C 中函数参数中的一些指针的理解,所以如果有人能向我解释,我将非常感激。

这是我的主要代码。函数 getOrder 应该只是剪切 ';' 之后的字符串并将第二部分(此处为“on”)发送回 bu 变量缓冲区。

char na[] = "2;on";
char* bu="on";

//This part Do conditional jump
getOrder(na, 4, &bu);

//This part Doesn't do conditional jump
//char copy[strlen(na)];
//strcpy(copy, na);

//bu=strtok(na,";");

bu[2]='\0';

printf("ending : %s\n",bu); //(<- this is the line 54 of the valgrind error)

这是 getOrder 函数:

//TODO conditional jump here ! Only whn returning from the function
char* getOrder(char order[], int size, char* res[]){
int i=0;
char copy[size];
strcpy(copy, order);

printf("\nstr: %s\n", copy);
*res=strtok(copy,";");
printf("tok : %s\n", *res);
*res=strtok(NULL, ";");
printf("tok : %s\n", *res); 
printf("%d and order is %s\n",strcmp(*res, "on"), *res);

return *res;
}

我不明白的是,为什么当我使用 getOrder 函数时,Valgrind 会抱怨这一切:

==7072== Conditional jump or move depends on uninitialised value(s)
==7072==    at 0x4E7EC15: vfprintf (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4E88748: printf (in /usr/lib64/libc-2.20.so)
==7072==    by 0x400A0D: main (test.c:54)
==7072== 
==7072== Conditional jump or move depends on uninitialised value(s)
==7072==    at 0x4EAEBC9: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4E7EBB5: vfprintf (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4E88748: printf (in /usr/lib64/libc-2.20.so)
==7072==    by 0x400A0D: main (test.c:54)
==7072== 
==7072== Conditional jump or move depends on uninitialised value(s)
==7072==    at 0x4EAEBD7: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4E7EBB5: vfprintf (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4E88748: printf (in /usr/lib64/libc-2.20.so)
==7072==    by 0x400A0D: main (test.c:54)
==7072== 
==7072== Syscall param write(buf) points to uninitialised byte(s)
==7072==    at 0x4F25E90: __write_nocancel (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4EAE49C: _IO_file_write@@GLIBC_2.2.5 (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4EAF948: _IO_do_write@@GLIBC_2.2.5 (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4EAEB5C: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4E7EB55: vfprintf (in /usr/lib64/libc-2.20.so)
==7072==    by 0x4E88748: printf (in /usr/lib64/libc-2.20.so)
==7072==    by 0x400A0D: main (test.c:54)
==7072==  Address 0x4022009 is not stack'd, malloc'd or (recently) free'd
==7072== 

但是当我在 main 中直接使用相同的东西时就不会了。基本上这些错误来自我使用函数 getOrder 的方式(无论是在参数中,还是我发送的指针),但我无法找到我的错误是什么。

非常感谢您的帮助。

c arrays pointers char valgrind
2个回答
1
投票

因为

res
end 是指向
copy
的指针,并且副本会随着
getOrder
函数的堆栈帧一起删除,因为它是局部变量。

试试这个

// TODO conditional jump here ! Only when returning from the function
char* getOrder(char order[], int size)
{
    int i=0;
    char copy[size];
    char *res;

    strcpy(copy, order);

    printf("\nstr: %s\n", copy);

    res = strtok(copy, ";");
    if (res == NULL) /* always check the return value from strtok */
        return NULL;
    printf("tok : %s\n", res);

    res = strtok(NULL, ";");
    if (res == NULL) /* always check the return value from strtok */
        return NULL;
    printf("tok : %s\n", res);
    printf("%d and order is %s\n", strcmp(res, "on"), res);

    return order + (res - copy);
}

并且

size
调用中的
getOrder
参数应该是
5
而不是
4
,因为有
4
字符 + 终止空字节
'\0'

char *na = "2;on";
char *bu;

//This part Do conditional jump
bu = getOrder(na, 5);

//This part Doesn't do conditional jump
//char copy[strlen(na)];
//strcpy(copy, na);

//bu=strtok(na,";");

//bu[2] = '\0';

if (bu != NULL)
    printf("ending : %s\n", bu); //(<- this is the line 54 of the valgrind error)
return 0;

1
投票

bu
只是只读的。你不能做这样的事情:

bu[2] = '\0';

这会崩溃。

回到你的问题,如果你想让字符串的第二部分是另一个数组,那么它可以像这样完成,而不需要函数。

PS:

strtok()
将修改传递的实际字符串,因此最好保留它的副本并传递副本。

#include <stdio.h>

int main(void) {
    char na[]="2;on";
    char bu[3];
    char *tok;
    tok = strtok(na,";");
    if(tok != NULL)
    printf("%s\n",tok);
    tok = strtok(NULL,";");
    if(tok != NULL)
    strcpy(bu,tok);
    printf("%s\n",bu);
    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.