Мне нужно заполнить мою структуру my_s1 данными. Я передаю его функции get_data(), которая должна делать всю грязную работу. У меня проблема с элементом b моей структуры, который является указателем. Я понятия не имею, как правильно присвоить значение, указанное (char *) buff, b без ошибок сегментации или ошибок valgrind.
Например:
Почему начальный p1->b="abc"; работает нормально, но если я попытаюсь использовать strcpy() или назначить через "=" оператор массива в p1->b я получаю ошибки?
Выделяет ли s1 my_s1 память для b или я должен как-то сам использовать malloc() p1->b? Но опять же мне нужно освободить() его и присвоить указатель NULL перед возвратом из функции, что противоречит цели (функция присваивает данные структуре), верно?
С текущим кодом, указанным ниже, у меня есть «правильный результат выполнения», но я также получаю следующие ошибки вывода valgrind (насколько я понимаю, поправьте меня, если я ошибаюсь, кажется, что printf() обращается к неправильно выделенной памяти - так что в этом случае это работает, но это мусор):
валгринд:
==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 для управления успехи/неудачи, или я должен писать функцию, которая вместо этого возвращает измененную структуру?
Это мой первый пост здесь, так что, пожалуйста, потерпите меня, мои ошибки форматирования, стены текста и мое невежество.
Заранее спасибо,
Том