我需要能够用数据填写我的my_s1结构。我将它传递给get_data()函数,该函数应该完成所有肮脏的工作。我遇到的问题是我的结构成员是指针。我不知道如何正确地分配(char *)buff到b指向的值,而没有分段错误或valgrind错误。
例如:将字符串赋值给C中的一个结构成员(指针)
为什么初始P1-> B = “ABC”;工作正常,但如果我尝试strcpy()或通过“=”运算符分配到p1-> b我得到错误?
是否S1 my_s1分配为b内存还是应该我莫名其妙的malloc()P1-> b自己?但是,我又需要释放()它并在从函数返回之前分配一个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: [email protected]@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: [email protected]@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: [email protected]@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来控制成功/失败或者我应该写一个函数返回一个修改后的结构呢?
这是我在这里的第一篇文章,所以请忍受我,我的格式错误,文字墙和我的无知。
由于提前,
汤姆
我怀疑你对指针指向在指针和事物之间的差异基本误解。当你在C中“分配一个字符串”时,你只能分配指针。实际的字符数据不会移动。 –
为什么在malloc之后立即释放?您也可以在释放缓冲区后访问p1-> b! p1-> b只是一个指向缓冲区的指针,当你确定不再使用缓冲区时,你只能释放缓冲区。 – moeCake
非常感谢@moeCake,我不是在get_data()函数中释放buff,而是在main()末尾释放(my_s1.b),而不是获取内存泄漏或valgrind错误。 – wymiata3