我需要能够用数据填写 my_s1 结构。我将它传递给get_data()函数,该函数应该执行所有脏工作。我遇到的问题是我的结构的 b 成员,它是一个指针。我不知道如何正确地将(char *)buff 指向的值分配给 b 而没有分段错误或valgrind错误。
例如:
为什么初始 p1-> b =“abc”; 工作正常,但如果我尝试 strcpy()或通过“ = “运营一个数组到 p1-> b 我得到错误?
s1 my_s1 是否为 b 分配内存,或者我应该以某种方式 malloc() p1-&gt; b < / em>我自己?但是我再次需要释放()并在从函数返回之前分配一个NULL指针,这违背了目的(将函数分配给结构的函数),对吗?
使用下面列出的当前代码,我有“正确的执行结果”,但我也得到以下valgrind输出错误(据我所知,请纠正我,如果我错了,似乎 printf ()访问没有正确分配的内存 - 所以它适用于这种情况,但它是垃圾):
的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来控制成功/失败或者我应该编写一个返回修改结构的函数吗?
这是我在这里的第一篇文章,所以请耐心等待我,我的格式错误,文字墙和我的无知。
提前谢谢,
汤姆
答案 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