将字符串分配给C中的结构成员(指针)

时间:2013-12-09 01:08:22

标签: c string struct valgrind assign


我需要能够用数据填写 my_s1 结构。我将它传递给get_data()函数,该函数应该执行所有脏工作。我遇到的问题是我的结构的 b 成员,它是一个指针。我不知道如何正确地将(char *)buff 指向的值分配给 b 而没有分段错误或valgrind错误。
例如:

  1. 为什么初始 p1-> b =“abc”; 工作正常,但如果我尝试 strcpy()或通过“ = “运营一个数组到 p1-> b 我得到错误?

  2. s1 my_s1 是否为 b 分配内存,或者我应该以某种方式 malloc() p1-&gt; b < / em>我自己?但是我再次需要释放()并在从函数返回之前分配一个NULL指针,这违背了目的(将函数分配给结构的函数),对吗?

  3. 使用下面列出的当前代码,我有“正确的执行结果”,但我也得到以下valgrind输出错误(据我所知,请纠正我,如果我错了,似乎 printf ()访问没有正确分配的内存 - 所以它适用于这种情况,但它是垃圾):

  4. 的valgrind:

    ==1067== Memcheck, a memory error detector
    ==1067== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
    ==1067== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
    ==1067== Command: ./if
    ==1067== Parent PID: 1059
    ==1067==
    ==1067== Invalid read of size 1
    ==1067==    at 0x4E7ADF9: vfprintf (in /usr/lib64/libc-2.17.so)
    ==1067==    by 0x4E83E38: printf (in /usr/lib64/libc-2.17.so)
    ==1067==    by 0x4005EF: main (iface.c:10)
    ==1067==  Address 0x51f3040 is 0 bytes inside a block of size 5 free'd
    ==1067==    at 0x4C294C4: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-
    linux.so)
    ==1067==    by 0x40064D: get_data (ifacelib.c:17)
    ==1067==    by 0x4005D3: main (iface.c:8)
    ==1067==
    ==1067== Invalid read of size 1
    ==1067==    at 0x4EA9459: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.17.
    so)
    ==1067==    by 0x4E7ADB1: vfprintf (in /usr/lib64/libc-2.17.so)
    ==1067==    by 0x4E83E38: printf (in /usr/lib64/libc-2.17.so)
    ==1067==    by 0x4005EF: main (iface.c:10)
    ==1067==  Address 0x51f3043 is 3 bytes inside a block of size 5 free'd
    ==1067==    at 0x4C294C4: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-
    linux.so)
    ==1067==    by 0x40064D: get_data (ifacelib.c:17)
    ==1067==    by 0x4005D3: main (iface.c:8)
    ==1067==
    ==1067== Invalid read of size 1
    ==1067==    at 0x4EA946C: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.17.
    so)
    ==1067==    by 0x4E7ADB1: vfprintf (in /usr/lib64/libc-2.17.so)
    ==1067==    by 0x4E83E38: printf (in /usr/lib64/libc-2.17.so)
    ==1067==    by 0x4005EF: main (iface.c:10)
    ==1067==  Address 0x51f3042 is 2 bytes inside a block of size 5 free'd
    ==1067==    at 0x4C294C4: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-
    linux.so)
    ==1067==    by 0x40064D: get_data (ifacelib.c:17)
    ==1067==    by 0x4005D3: main (iface.c:8)
    ==1067==
    ==1067== Invalid read of size 4
    ==1067==    at 0x4EBBDDE: __GI_mempcpy (in /usr/lib64/libc-2.17.so)
    ==1067==    by 0x4EA939C: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib64/libc-2.17.
    so)
    ==1067==    by 0x4E7ADB1: vfprintf (in /usr/lib64/libc-2.17.so)
    ==1067==    by 0x4E83E38: printf (in /usr/lib64/libc-2.17.so)
    ==1067==    by 0x4005EF: main (iface.c:10)
    ==1067==  Address 0x51f3040 is 0 bytes inside a block of size 5 free'd
    ==1067==    at 0x4C294C4: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-
    linux.so)
    ==1067==    by 0x40064D: get_data (ifacelib.c:17)
    ==1067==    by 0x4005D3: main (iface.c:8)
    ==1067==
    ==1067==
    ==1067== HEAP SUMMARY:
    ==1067==     in use at exit: 0 bytes in 0 blocks
    ==1067==   total heap usage: 1 allocs, 1 frees, 5 bytes allocated
    ==1067==
    ==1067== All heap blocks were freed -- no leaks are possible
    ==1067==
    ==1067== For counts of detected and suppressed errors, rerun with: -v
    ==1067== ERROR SUMMARY: 10 errors from 4 contexts (suppressed: 2 from 2)
    

    3个文件中的代码。

    ifacelib.h:

    #ifndef IFACELIB_H
    #define IFACELIB_H
    
    typedef struct
    {
        int a;
        char * b;
    } s1;
    
    int get_data(s1 *);
    
    #endif
    

    ifacelib.c:

    #include "ifacelib.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int get_data(s1 *p1)
    {
        char *buff;
        p1->a=1;
        p1->b="abc";
    
        buff = (char *) malloc(strlen("test")*sizeof(char)+1);
        strcpy(buff, "test");
    
        p1->b = buff;
    
        free(buff);
        buff = NULL;
    
        return 0;
    }
    

    iface.c:

    #include "ifacelib.h"
    #include <stdio.h>
    
    int main()
    {
        s1 my_s1;
    
        if ((get_data(&my_s1))==0)
        {
            printf("a= %d\tb= %s\n", my_s1.a, my_s1.b);
        }
    
        return 0;
    }
    

    任何帮助或只是指向正确的方向将不胜感激。

    最佳实践的角度来看,在使用结构时,我应该编写一个函数来填充结构中的数据(在传递的结构上工作)并返回int来控制成功/失败或者我应该编写一个返回修改结构的函数吗?

    这是我在这里的第一篇文章,所以请耐心等待我,我的格式错误,文字墙和我的无知。
    提前谢谢,
    汤姆

2 个答案:

答案 0 :(得分:1)

你做错了,很幸运能得到正确的结果,实际上你正在访问刚被释放的记忆 你必须使用malloc来获取struct中的char *(顺便说一句,你可以使用strdup),但是你需要另一个析构函数来在结束工作时释放结构。
在你的情况下,你需要在printf之后使用像free_s1这样的函数,而不是在构造函数(get_data)中自由。

答案 1 :(得分:0)

这适用于C,在C ++中不太好:

如果你要使用malloc(),最好一次性地对你的结构和数据区域进行malloc。而不是让指针在结构的末尾排列最小的数据区域。分配struct时,添加额外的字节以允许数据。你很高兴去。一个免费将释放结构和数据。

重新编写代码片段以显示我得到以下内容的关键想法。我为学生留下编译,调试,甚至语法检查。

typedef struct
{
    int a;
    char * b;
    char   data[1];    // data goes here. 
                       // structure MUST be malloced at run time WITH
                       //  extra storage for data.
} s1;
    s1   *p1;
    data = "test";
    data_len = strlen(data);       // additional bytes of storage
    p1 = malloc( data_len + sizeof( *p1 ) );  // allocate structure + data
    strcpy(s1->data, data );        // copy data to buffer

    ...
    free(p1);        // free storage