memcpy-ing to a feild of a struct pointer in c - c

I am having trouble with struct pointers....Here are two examples in my code that are essentially doing the same thing except dsp is not a pointer and InMemory[Idx] is a pointer, how to I use memcpy in the pointer case?
my_struct* InMemory[SIZE]
//works prints: tmp3:local_file (file name)
memcpy(dsp.result.list[i].owner_name,req.file_name,256);
char tmp3[256];
memcpy(tmp3,dsp.result.list[i].owner_name,256);
printf("tmp3:%s\n",tmp3);
//doesn't work, prints: tmp:_____<---nothing! ??
//I am trying to copy the result from above into a field of the struct pointer array
char tmp2[256];
memcpy(InMemory[Idx]->filename,dsp.result.list[i].owner_name,256);
memcpy(tmp2,InMemory[Idx]->filename,256);
printf("tmp:%s\n",tmp2);

From your code, you have not allocated member elementes of InMemory
for (i=0;i<SIZE;i++)
{
// allocate elements here
InMemory[i]->filename = malloc(....)
// other allocations
}
// now use memcpy

Related

How to free and write to NULL a pointer in an array inside a struct, indirectly via pointer to struct?

I have to set a reference pointed by a pointer to NULL.
But the function deleteP(...) doesn't seem to work, indicated by the Output.
The functions delete() and memoryset() work in some way, even if the latter just fills the memory (pointed to by the pointer in the array) with zeroes.
I want the pointer in the array to finally be NULL and that is not working.
I need to do everything (i.e. set fs->child[20] to NULL etc.) via pointer to the struct (which is elin my code, a local pointer variable inside deleteP(...) ). This is because I am iterating over fs children, and their children after that, a lot of times, and I put the current child in el.
How could I solve it?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define HEIGHT 255
#define LENGTH 256
#define MAX_CHILDREN 1024
typedef struct FS FS;
typedef struct Elem Elem;
struct Elem {
char name[LENGTH];
char content[256];
int isFile;
int emptyCells;
Elem *child[MAX_CHILDREN];
};
struct FS {
int emptyCells;
Elem *child[MAX_CHILDREN];
};
void delete(FS *fs){
free(fs->child[20]);
fs->child[20] = NULL;
}
void deleteP(FS *fs){
Elem *el = calloc(1, sizeof (Elem));
el = fs->child[20];
free(el);
el = NULL;
}
void memoryset(FS *fs){
Elem *el = calloc(1, sizeof (Elem));
el = fs->child[20];
memset(el, 0, sizeof(Elem));
}
int main(int argc, const char * argv[]) {
FS *fs = calloc (1, sizeof(FS));
fs->emptyCells = MAX_CHILDREN;
fs->child[20] = calloc (1, sizeof(Elem));
strcpy(fs->child[20]->name, "Hello");
printf("No delete: %s\n", fs->child[20]->name);
memoryset(fs);
printf("MEMSET: %s\n", fs->child[20]->name);
fs->child[20] = calloc (1, sizeof(Elem));
strcpy(fs->child[20]->name, "Hello");
delete(fs);
printf("Delete: %s\n", fs->child[20]->name);
fs->child[20] = calloc (1, sizeof(Elem));
strcpy(fs->child[20]->name, "Hello");
deleteP(fs);
printf("DeleteP: %s\n", fs->child[20]->name);
}
Output:
No delete: Hello
MEMSET:
Delete: (null)
DeleteP: Hello
Allow me to phrase your goal in my words
(after verifying my understanding in chat):
you want to free memory pointed to by a pointer which is stored in an array,
which is inside a struct, which you get a pointer to
you cannot access the array member directly,
only via the pointer to the containing struct
you also want to write NULL to the array member
looking at your code, you attempted to do that by making a copy of the array member (which is a pointer)
it mostly works, only that the array member does not end up being NULL
(and some problems mentioned by xing and BLUEPIXY)
Basically, you need a pointer to the array member, instead of a copy of the array member.
So your function should be:
void deleteP(FS *fs){
Elem **el; // pointer to pointer, instead of pointer (and no calloc)
el = &(fs->child[20]); // pointer to array member
free(*el); // free the pointer in the array member (not a copy of it),
// though the effect is the same
*el = NULL; // write NULL to the array member, not a copy of it,
// this is what changes the effect to what you want
}
If I did not mistype anything, this is more or less the result of our chat.
And as far as I understand, it solves your problem. Cheers.
As far as I can tell, this should also fix the memory leak found by xing inside deleteP(...).
But be careful to also fix it in memoryset(...).
This does NOT fix the problems of UB (undefined behaviour) as found by BLUEPIXY.
For this you need to rework your debug prints and make sure not to dereference any pointers to already freed memory (question of order of doing things) and also not to dereference any pointer which was set to NULL.
By the way, this could be done without a local pointer variable; doing everything via the parameter fs. But I kept the solution closer to your own code for better clarity of what is the difference. Also in my opinion your way of doing it via local pointer is more readable. It might even be faster, but seeing how good modern compilers are, I doubt it; the actual reason is clarity and readability.

Passing an Array of Structures

How can I pass an array of structures?
So far I have this which is global:
typedef struct _line
{
float val1;
int val2;
} line;
Then I read data from a file into this structure
struct _line* read_file()
{
typedef struct _line *Lines
Lines *array = malloc(num_lines * sizeof(Lines));
//read values into structures here
Then I fill up the structures in the array with values. If I do printf("%d", (*array[1]).val1); I get the right value here in this particular method
Then I return the array like so
return *array
But when I do so, only the 0th structure reads correctly in the method I returned to. Reading the 1st element just prints random values. What am I doing incorrectly?
You should not dereference the array when you return it1, it's actually of incompatible type with the function return type, just
return array;
also, check that array != NULL after malloc() before reading the values, and you don't really need the typedef it makes your code a bit confusing.
If your code compiled which I doubt, then you don't have warnings enabled in your compiler command, enable them so you can prevent this kind of issue.
(1) *array is equivalent to array[0].
Expanding on my comments, your code (as you describe and show it) you have undefined behavior:
This is because you allocate an array of pointers, but you apparently do not allocate the pointers in that array. So when you dereference a pointer (which you haven't allocated and whose value is indeterminate and so will point to a seemingly random location) you have this undefined behavior.
Instead of using a type-alias like Line use the structure name, like
struct _line *array = malloc(num_lines * sizeof(*array));
That will allocate num_lines structures (instead of pointers), then you use it like a normal array, without the pointer dereferencing
array[x].val1 = something;
And you of course return that pointer array as-is:
return array;

Freeing a pointer in a structure referenced by a pointer

I have a pointer to several structures that have been allocated memory via:
STRUCTNAME *ptr;
ptr = (STRUCTNAME *)malloc(sizeof(STRUCTNAME)*numberOfStructs);
The structures are accessed via a offset like so:
(ptr + i)->field;
The structures have 2 fields that are character pointers as follows:
typedef struct
{
char *first;
char *second;
}STUCTNAME;
These fields are allocated memory as follows:
(ptr + i)->first = (char *)malloc(strlen(buffer));
This appears to work but when I try to free the pointers within the structures I get a segmentation fault 11 when I do this:
free((prt + i)->first);
Help?
Notes:
buffer is a character array. Offsetting a pointer by a integer should increment the pointer by the size of what it is pointing to times the integer correct?
Here is a link to my full source code. I have not written some of the functions and I am not using the freeAllpointers and printAll yet.
https://drive.google.com/file/d/0B6UPDg-HHAHfdjhUSU95aEVBb0U/edit?usp=sharing
OH! Thanks everyone! Have a happy Thanksgiving! =D (If you're into that kinda stuff)
In case, you don't initialize all those members in that piece of code, you're not showing us:
Allocate the struct storage (STRUCTNAME*) with calloc(), so that all allocated memory, namely firstand second are zero at the beginning. Passing NULL to free() will result in a no-op. Passing any wild (garbage) pointer to free() may cause a segmentation fault.
To detect a double-free, set ptr[i].first = NULL; after free(ptr[i].first); as a defensive measure for testing.
Notes: buffer is a character array. Offsetting a pointer by a integer
should increment the pointer by the size of what it is pointing to
times the integer correct?
Yes, except for void* on those compilers, which don't define sizeof(void), which is defined to have undefined behavior, to a value > 0: What is the size of void?
Edit:
void makeReviews(FILE *input, REVIEW *rPtr, int numReviews) <-- This does NOT return the new value of rPtr. In main(), it will remain NULL.
Do something like this:
REVIEW* makeReviews(FILE *input, int numReviews);
//...
int main(){
//...
rPtr = makeReviews(input,numReviews);
//...
}
or
void makeReviews(FILE** input,REVIEW** rPtrPtr,int numReviews){
REVIEW* rPtr = *rPtrPtr;
//...
*rPtrPtr = rPtr;
}
//...
int main(){
//...
makeReviews(input,&rPtr,numReviews);
//...
}
fgets(cNumReviews, sizeof(cNumReviews), input); <-- Perhaps, you could use something like fscanf().

Changing values in elements of an array of structs

I am working on an assignment and ran into challenging problem. As far as I'm concerned and from what I've learnt the code that follows should be correct however it does not work. Basically what I am trying to is copy a string value into the variable member of a structure the is part of an array passed into a method as a pointer. What am I missing?
typedef struct
{
char * name; //variable in struct I am trying to access
} Struct;
void foo(Struct * arr) //array of Structs passed into function as a pointer
{
int i = 0;
while(i++ < 2)
{
arr[i].name = malloc(sizeof(char *)); //assigning memory to variable in each Struct
arr[i].name = strdup("name"); //copying "name" to variable in each Struct
printf("C - %s\n", arr[i].name); //printing out name variable in each Struct
}
}
main()
{
Struct * arr; //defining pointer
arr = calloc(2, sizeof(Struct)); //allocating memory so pointer can hold 2 Structs
foo(arr); //calling function foo passing pointer into function
return 0;
}
This code compiles and runs however it does not do what it is designed to do. Forgive me if it is something trivial. I am new to the language C
Two issues:
while(i++ < 2) This line changes the value of i as soon as it checks it, so your loop body will not be the same as it was checked.
arr[i].name = strdup("name"); overwrites the value of the .name pointer, causing a memory leak of the memory you malloc()'ed earlier.
Extending on 2 pointed out correctly already,
arr[i].name = strdup("name");
Even if you use following instead of above,
strcpy(array[i].name, "name");
you haven't allocated enough bytes to store the string i.e. this is wrong
arr[i].name = malloc(sizeof(char *));
// even if pointer is 8 byte here, concept isn't right
Should be something like
arr[i].name = malloc(strlen("name")+1);
// or MAX_SIZE where it is greater than the possible "name".
Or better yet, remove the malloc at all, strdup takes care of allocation itself
This is not answering your question directly, but addresses an issue to big to put into a comment...
Additional issue: You probably did not intend to allocate only a (char *) worth of memory to a variable intended to hold at least "name". Change;
arr[i].name = malloc(sizeof(char *));
to:
arr[i].name = malloc(sizeof(char)*strlen("name")+1); //+1 for '\0'
or better yet, use char *name="name";, then:
arr[i].name = malloc(sizeof(char)*strlen(name)+1);
Even more general (and better):
char *name;
name = malloc(strlen(someInputString)+1);
//do stuff with name...
free(name);
Now, you can allocate name to any length needed based on the length of someInputString.
[EDIT]
Etienz, I wanted to address one more thing, alluded to by #H2CO3 above, but not really explained, that I think might be useful to you:
Regarding your desire to have room for two structs, because you typedef'd your struct, you can simply do something like this: (but I am going to change the name you used from Struct to NAME :) The whole point being that when a struct is created as an array, you do not need to use calloc or malloc to create space for them, it is done as shown below...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char *name;
}NAME;
//use new variable type NAME to create global variables:
NAME n[2], *pN; //2 copies AND pointer created here
//prototype func
int func(NAME *a);
int main()
{
pN = &n[0]; //pointer initialized here
func(pN); //pointer used here (no malloc or calloc)
printf("name1 is %s\nname 2 is %s", pN[0].name, pN[1].name);
return 0;
}
int func(NAME *a)
{
char namme1[]="andrew";
char namme2[]="billebong";
//You DO have to allocate the members though
a[0].name = malloc(strlen(namme1)+1);
a[1].name = malloc(strlen(namme2)+1);
strcpy(a[0].name, namme1);
strcpy(a[1].name, namme2);
return 0;
}

c malloc in other function and structs

Im having problems with c and pointers. I keep grinding on this and it has to be easy. I have a struct and I allocate in one function, then pass the pointer back to the original function. But when I try to fill the values of the struct with other variables, and then print them or copy them , the app segfaults saying the memory address is out of bounds.
struct memcache_buffer{
int elements, action;
char keys[MAX_KEYS], values[MAX_KEYS], returns[MAX_KEYS]; //action 0 = delete , 1 = get 2 = set
}memcache_buffer;
struct memcache_buffer* memcache_allocate_buffer(int size){
struct memcache_buffer *buffer;
buffer =malloc(sizeof(struct memcache_buffer));
return buffer;
}
void memcache_set(char * key, char * value){
pthread_t process_t;
struct memcache_buffer *buffer=memcache_allocate_buffer(1);
char keys,values;
buffer->elements = 1;
buffer->action=2;
//printf("crash?\n");
printf("%s %s",key,value);
snprintf(buffer->keys[0],KEY_SIZE,"%s",key);
snprintf(buffer->values[0],VALUE_SIZE,"%s",value);
pthread_create(&process_t,NULL,memcache_process,buffer);
}
am I allocating the memory right? allocating memory and these pointers are sure rough, especially only messing with php in the past.
Here's your problem:
struct memcache_buffer{
char keys[MAX_KEYS], values[MAX_KEYS]
}
snprintf(buffer->keys[0],KEY_SIZE,"%s",key);
^^^
snprintf(buffer->values[0],VALUE_SIZE,"%s",value);
^^^
Drop the [0] or snprintf will try to dereference some bogus value.

Resources