我需要能夠用數據填寫我的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