在结构

时间:2017-09-19 04:16:13

标签: c string struct valgrind

我正在尝试编写一个程序,我可以在其中创建令牌,使每个令牌具有常量类型和值。

token.h:

#ifndef TOKEN_H
#define TOKEN_H
typedef struct{
    const char *type;
    const char *value;
}token;

token *gen_token(const char *r, const char *val);

#endif

token.c:

#include <stdlib.h>
#include <string.h>
#include "lib/token.h"

token *gen_token(const char *type, const char *val){
    token o = {type, val}, *out = &o;
    return out;
}

main.c中:

#include <stdio.h>
#include <stdlib.h>
#include "lib/token.h"

int main(int argi, char *argv[]){
    const char th[] = "line", va[] = ":";

    token *t = gen_token(th, va);

    printf("(%s, %s)\n", t->type, t->value);

    return 0;
}

当我正常运行时,似乎没有出现错误,但是当valgrind看一下它时,它会抱怨很多。这是我的日志:

==4086== Memcheck, a memory error detector
==4086== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==4086== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==4086== Command: ./a lol
==4086== 
==4086== Conditional jump or move depends on uninitialised value(s)
==4086==    at 0x4E7FD4F: vfprintf (vfprintf.c:1637)
==4086==    by 0x4E871F8: printf (printf.c:33)
==4086==    by 0x1087AB: main (main.c:11)
==4086==  Uninitialised value was created by a stack allocation
==4086==    at 0x108785: main (main.c:10)
==4086== 
==4086== Use of uninitialised value of size 8
==4086==    at 0x4C2EBE2: strlen (vg_replace_strmem.c:458)
==4086==    by 0x4E80D77: vfprintf (vfprintf.c:1637)
==4086==    by 0x4E871F8: printf (printf.c:33)
==4086==    by 0x1087AB: main (main.c:11)
==4086==  Uninitialised value was created by a stack allocation
==4086==    at 0x108785: main (main.c:10)
==4086== 
==4086== Use of uninitialised value of size 8
==4086==    at 0x4C2EBF4: strlen (vg_replace_strmem.c:458)
==4086==    by 0x4E80D77: vfprintf (vfprintf.c:1637)
==4086==    by 0x4E871F8: printf (printf.c:33)
==4086==    by 0x1087AB: main (main.c:11)
==4086==  Uninitialised value was created by a stack allocation
==4086==    at 0x108785: main (main.c:10)
==4086== 
==4086== Conditional jump or move depends on uninitialised value(s)
==4086==    at 0x4EAAEEB: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1307)
==4086==    by 0x4E80BBA: vfprintf (vfprintf.c:1637)
==4086==    by 0x4E871F8: printf (printf.c:33)
==4086==    by 0x1087AB: main (main.c:11)
==4086==  Uninitialised value was created by a stack allocation
==4086==    at 0x108785: main (main.c:10)
==4086== 
==4086== Use of uninitialised value of size 8
==4086==    at 0x4EAAEF1: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1309)
==4086==    by 0x4E80BBA: vfprintf (vfprintf.c:1637)
==4086==    by 0x4E871F8: printf (printf.c:33)
==4086==    by 0x1087AB: main (main.c:11)
==4086==  Uninitialised value was created by a stack allocation
==4086==    at 0x108785: main (main.c:10)
==4086== 
==4086== Conditional jump or move depends on uninitialised value(s)
==4086==    at 0x4EAAF03: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1307)
==4086==    by 0x4E80BBA: vfprintf (vfprintf.c:1637)
==4086==    by 0x4E871F8: printf (printf.c:33)
==4086==    by 0x1087AB: main (main.c:11)
==4086==  Uninitialised value was created by a stack allocation
==4086==    at 0x108785: main (main.c:10)
==4086== 
==4086== Use of uninitialised value of size 8
==4086==    at 0x4EAAF0D: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1309)
==4086==    by 0x4E80BBA: vfprintf (vfprintf.c:1637)
==4086==    by 0x4E871F8: printf (printf.c:33)
==4086==    by 0x1087AB: main (main.c:11)
==4086==  Uninitialised value was created by a stack allocation
==4086==    at 0x108785: main (main.c:10)
==4086== 
==4086== Conditional jump or move depends on uninitialised value(s)
==4086==    at 0x4C32EB3: is_overlap (vg_replace_strmem.c:137)
==4086==    by 0x4C32EB3: __GI_mempcpy (vg_replace_strmem.c:1525)
==4086==    by 0x4EAAE23: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1327)
==4086==    by 0x4E80BBA: vfprintf (vfprintf.c:1637)
==4086==    by 0x4E871F8: printf (printf.c:33)
==4086==    by 0x1087AB: main (main.c:11)
==4086==  Uninitialised value was created by a stack allocation
==4086==    at 0x108785: main (main.c:10)
==4086== 
==4086== Conditional jump or move depends on uninitialised value(s)
==4086==    at 0x4C32EB9: is_overlap (vg_replace_strmem.c:140)
==4086==    by 0x4C32EB9: __GI_mempcpy (vg_replace_strmem.c:1525)
==4086==    by 0x4EAAE23: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1327)
==4086==    by 0x4E80BBA: vfprintf (vfprintf.c:1637)
==4086==    by 0x4E871F8: printf (printf.c:33)
==4086==    by 0x1087AB: main (main.c:11)
==4086==  Uninitialised value was created by a stack allocation
==4086==    at 0x108785: main (main.c:10)
==4086== 
==4086== Conditional jump or move depends on uninitialised value(s)
==4086==    at 0x4C32EC7: __GI_mempcpy (vg_replace_strmem.c:1525)
==4086==    by 0x4EAAE23: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1327)
==4086==    by 0x4E80BBA: vfprintf (vfprintf.c:1637)
==4086==    by 0x4E871F8: printf (printf.c:33)
==4086==    by 0x1087AB: main (main.c:11)
==4086==  Uninitialised value was created by a stack allocation
==4086==    at 0x108785: main (main.c:10)
==4086== 
==4086== Conditional jump or move depends on uninitialised value(s)
==4086==    at 0x4C32ECC: __GI_mempcpy (vg_replace_strmem.c:1525)
==4086==    by 0x4EAAE23: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1327)
==4086==    by 0x4E80BBA: vfprintf (vfprintf.c:1637)
==4086==    by 0x4E871F8: printf (printf.c:33)
==4086==    by 0x1087AB: main (main.c:11)
==4086==  Uninitialised value was created by a stack allocation
==4086==    at 0x108785: main (main.c:10)
==4086== 
==4086== Conditional jump or move depends on uninitialised value(s)
==4086==    at 0x4C32F64: __GI_mempcpy (vg_replace_strmem.c:1525)
==4086==    by 0x4EAAE23: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1327)
==4086==    by 0x4E80BBA: vfprintf (vfprintf.c:1637)
==4086==    by 0x4E871F8: printf (printf.c:33)
==4086==    by 0x1087AB: main (main.c:11)
==4086==  Uninitialised value was created by a stack allocation
==4086==    at 0x108785: main (main.c:10)
==4086== 
==4086== Use of uninitialised value of size 8
==4086==    at 0x4C32F70: __GI_mempcpy (vg_replace_strmem.c:1525)
==4086==    by 0x4EAAE23: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1327)
==4086==    by 0x4E80BBA: vfprintf (vfprintf.c:1637)
==4086==    by 0x4E871F8: printf (printf.c:33)
==4086==    by 0x1087AB: main (main.c:11)
==4086==  Uninitialised value was created by a stack allocation
==4086==    at 0x108785: main (main.c:10)
==4086== 
==4086== Use of uninitialised value of size 8
==4086==    at 0x4C32F7E: __GI_mempcpy (vg_replace_strmem.c:1525)
==4086==    by 0x4EAAE23: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1327)
==4086==    by 0x4E80BBA: vfprintf (vfprintf.c:1637)
==4086==    by 0x4E871F8: printf (printf.c:33)
==4086==    by 0x1087AB: main (main.c:11)
==4086==  Uninitialised value was created by a stack allocation
==4086==    at 0x108785: main (main.c:10)
==4086==  (line, :)
==4086== 
==4086== HEAP SUMMARY:
==4086==     in use at exit: 0 bytes in 0 blocks
==4086==   total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==4086== 
==4086== All heap blocks were freed -- no leaks are possible
==4086== 
==4086== For counts of detected and suppressed errors, rerun with: -v
==4086== ERROR SUMMARY: 36 errors from 14 contexts (suppressed: 0 from 0)

我非常感谢对我的代码的任何帮助和/或批评。

2 个答案:

答案 0 :(得分:2)

在功能中

token *gen_token(const char *type, const char *val){
    token o = {type, val}, *out = &o;
    return out;
}

变量out指向局部变量o,它在函数返回后被释放。这是纯粹的意外,您可以在调用函数后读取这些值。因此有关于

的警告
  

未初始化的值是由堆栈分配

创建的

相反,您需要为其分配内存和复制值。 注意你需要记住在退出程序之前释放已分配的内存,特别是如果你想让valgrind高兴:)

答案 1 :(得分:0)

您在gen_token函数中返回automatic storage duration变量的地址。对于中的存储时间

  

存储是在输入声明对象的块时输入的,并且在退出时取消分配(转到,返回,到达结尾)。

注意:使用您从gen_token函数返回的地址是未定义的行为

我建议您使用opaque pointer技术作为示例,如下所示:

<强> token.h

#ifndef TOKEN_H
#define TOKEN_H

struct token; /* incomplete type, but you can use pointers to it */
typedef struct token token;

/* allocates memory for 'token' and initializes it */
token* gen_token(const char* r, const char* val);
/* deallocates the specified memory */
void delete_token(token* ptr);
/* returns the value of 'type' member */
const char* get_type(token* ptr);
/* returns the value of 'value' member */
const char* get_value(token* ptr);

#endif

<强> token.c

#include <stdlib.h>
#include "token.h"

/* the 'struct token' is defined here in the source file */
struct token {
    const char* type;
    const char* value;
};

token *gen_token(const char* type, const char* val) {
    token* out = (token*)malloc(sizeof(token));
    out->type = type;
    out->value = val;
    return out;
}
void delete_token(token* ptr) {
    free(ptr);
}
const char* get_type(token* ptr) {
    return ptr == NULL ? "" : ptr->value;
}
const char* get_value(token* ptr) {
    return ptr == NULL ? "" : ptr->type;
}

在上面的示例中,gen_tokentoken对象分配内存,对其进行初始化并返回已分配内存块的地址。 中的这种存储持续时间是分配的存储持续时间:

  

使用dynamic memory allocation functions分配并取消分配请求

样本用法:

#include <stdio.h>
#include <stdlib.h>
#include "token.h"

int main() {
    token* t = gen_token("line", ":");
    printf("(%s, %s)\n", get_type(t), get_value(t));
    return 0;
}

还有一件重要的事情。 main函数中的以下变量是具有自动存储持续时间的常量数组:

const char th[] = "line", va[] = ":";

您可以存储指向数组第一个元素的指针,但如果按如下方式执行,您将拥有dangling pointers

token* create_token() {
    const char th[] = "line", va[] = ":";
    return gen_token(th, va);
} /* from this point the created 'token' object will store dangling pointers */