I have declared the structure:
typedef struct keyValuePairs{
char* type;
char* key;
char* valueType;
char* value;
} keyValueType;
keyValueType keyValuePairs[1000];
And in a function declared the local variables as:
char key[500];
char value[500];
to hold the key value pair values as:
key[i]="abc";
value[i]="xyz"
I have assigned these local variables to the global variable as:
keyValuepairs[1].key=key.
Once i come out of the function, the values assigned in the structure is getting lost. Can someone explain where I am going wrong?
Please note I am fairly new to C.
Both key and value variables are pointers to arrays that are allocated in the stack when you are in the function. After keyValuepairs[1].key=key the global variable points to that same place in the stack. After exiting the function, the memory where those arrays were is reused.
I suggest you read up on static vs dynamic allocation in C
If I understand you correctly, you are trying something along the lines of:
typedef struct
{
char* val;
} A;
A alist[10];
void foo()
{
char t[10];
t = "abc";
alist[0].val = t;
}
int main()
{
foo();
}
First of all, the line
t = "abc";
is syntactically incorrect. You have to use something like:
strcpy(t, "abc");
But the most important error is that when you return from foo, alist[0].val points to an address that is not good any more. To make sure alist[0].val points to a valid address, you have to allocate memory from the heap for it and copy the contents of t to it.
void foo()
{
char t[10];
strcpy(t,"abc");
alist[0].val = malloc(strlen(t)+1);
strcpy(alist[0].val, t);
}
To do a thorough job, you'll have to make sure that you call free on that allocated memory at some point before you return from main.
You have not allocated memory for type, key, valueType and value.
Try static memory allocation :
typedef struct keyValuePairs{
char* type[n];
char* key[n];
char* valueType[n];
char* value[n];
}
Where n is a defined constant
Related
From what I know, if you create a global struct as follows:
something name;
int main(){
}
You are able to access every field of the struct something, but if I were to instead make it as:
something* name;
int main(){
}
Would this now be incorrect because I have to malloc the size of the struct?
Note, I haven't decided what the struct something contains, this is more of a general question.
Basically, pointer is just a variable that points to some address in memory. So after
something* name;
int main(){
}
all you have is a pointer. It should point to a place in memory, where struct
something exists, but for now its just garbage there (notice that pointer can point to random location and as long as you don't try to do something with it no error will occur). After calling malloc system will reserve space needed for something and return pointer you should assign to global variable.
Would this now be incorrect because I have to malloc the size of the struct?
Well, it depends on how you are going to use it.
Code like:
something* name;
int main(){
}
is by it self perfectly valid C code.
You can for instance use it like:
something* name;
int main(){
something x = {....};
name = &x; // Make name point to a "something" object
...
name->some_member = ...;
...
}
or like
something* name;
int main(){
something x = {....};
name = malloc(sizeof *name); // Make name point to a "something" object
assert(name != NULL);
...
name->some_member = ...;
...
}
But without an assignment to name like name = ... you can't dereference the pointer. In other words, this would be invalid
something* name;
int main(){
...
name->some_member = ...; // INVALID
...
}
because name doesn't point to a "something" object.
BTW:
Since name is global the code
something* name;
is the same as
something* name = NULL;
UNRELATED:
There are cases where global variables are good and useful but in most cases, it's best to avoid globals.
I have structure with char pointer. I want to allocate static memory to this struct member. How can I do this?
Example:
struct my_data {
int x;
bool y;
char *buf;
};
How to assign 10 bytes static memory to this char pointer? I know malloc to assign dynamic memory allocation. Is this Ok?
struct my_data data;
char buffer[10];
data.buf = &buffer[0];
PS: I am not allowed to change this struct and use malloc to assign dynamic memory.
That will be even simpler (array decays to pointer automatically):
data.buf = buffer;
note that buffer must have an ever-lasting lifetime or you have to make sure that it's not deallocated (i.e. routine where it is declared returns) while you're using it or referencing it.
Allocating from a subroutine and returning will cause underfined behaviour because memory will be deallocated on return.
For instance don't do this (as we often see in questions here):
struct my_data foo()
{
struct my_data data;
char buffer[10];
data.buf = &buffer[0];
return data;
}
int main()
{
struct my_data d = foo(); // buffer is already gone
Bugs introduced by this kind of UB are nasty because the code seems to work for a while, until the unallocated buffer gets clobbered by another function call.
I have a following problem in which I can't figure out how to assign a char* called funcName to a char* called fname. Need some help, thanks.
#define MAX_PARMS 5
typedef enum {C_INT, C_SHORT, C_CHAR, C_FLOAT, C_INT_PTR} DataType;
typedef struct {
char name;
int *value;
DataType dType;
} VarType;
typedef struct {
char *funcName;
VarType parms[MAX_PARMS];
int numParms;
} FrameType;
void enterSumFunc (StackType *stkPtr, char *fname, int num, int *arr, int *sum) {
FrameType *temp;
//temp->funcName = fname;
strcpy(temp->funcName, fname);
}
As you can see I have tried both strcpy and manually setting the char* but nothing works; both give a segmentation fault. Any help will be useful, thanks.
FrameType *temp;
temp->funcName ...
dereferences an uninitialized pointer, which yields undefined behavior, which in this case you are able to observe as segmentation fault. One of the possible solutions is using an object with automatic storage duration instead of pointer:
FrameType temp;
temp.funcName ...
Also note that
temp->funcName = fname;
assigns the value of pointer fname (i.e. an address it points to) to the pointer funcName, no copying is performed and once the memory associated with fname is freed, this temp->funcName will be an invalid (dangling) pointer and using it will also result in undefined behavior.
On the other hand:
strcpy(temp->funcName, fname);
tries to copy null-terminated string stored in fname to funcName and in case the string is not null terminated or there is no memory associated with this pointer, it will result in undefined behavior as well.
Note that:
typedef struct {
char *funcName;
VarType parms[MAX_PARMS];
int numParms;
} FrameType;
only declares a pointer funcName so you should either explicitly allocate a memory using malloc before trying to copy a string to it or yet even better, use a buffer with automatic storage duration instead:
typedef struct {
char funcName[255];
VarType parms[MAX_PARMS];
int numParms;
} FrameType;
temp is not set, so dereferencing it (->) will never be valid.
Based on edited code (specifying FrameType)
FrameType *temp = malloc(sizeof(FrameType));
temp->funcName = fname;
or
FrameType obj;
FrameType *temp = &obj;
temp->funcName = fname;
Will "work", but it's a "shallow copy" of data. If the "owner" of fname deletes it or changes it, then your temp object becomes invalid. You can either use strdup() to copy the name, or put a char[] in the FrameType instead of just a pointer.
If temp really is a temp (and doesn't have to live past the end of the function call) then the second approach is probably better.
Remember for each malloc you need a free or elase you will leak memory. The second approach shown above reduces that risk...
I want my struct to carry a string. I defined it like so:
typedef struct myStruct {
char* stringy
} myStruct
and a function
free(char *stringy){
//structObj is a struct object
structObj->stringy = stringy
}
Is this correct? I have a feeling that since it's a local variable, stringy will be lost, and the pointer will point to garbage.
Sorry, new with C.
It would be garbage if you were somehow using char** stringy, but structObj->stringy = stringy means "you know the thing that stringy points to? Now structObj->stringy points to that". Of course, it is still possible to unset the value which the pointer is pointing to, and at that point dereferencing will yield garbage.
Here's an example to make it clearer:
#include<stdio.h>
typedef struct mStruct {
char* stringy;
} myStruct;
myStruct * structObj;
void doSomething(char* stringy)
{
structObj->stringy = stringy;
}
int main(int argc, char* argv)
{
char* a = "abc\n";
structObj = malloc(sizeof(myStruct));
doSomething(a);
a = "qxr\n";
printf(structObj->stringy);
}// prints "abc\n"
If stringy is defined in callers of free function, as long as they keep the actual string in its place (where stringy points), no problem.
There is not any local variable declaration in your code.
You have to declare:
typedef struct myStruct {
char* stringy
} myStruct;
free(char *stringy){
myStruct *structObj;
structObj->stringy = stringy;
}
Pay attention to the semicolon that I've added to the end of the typedef declaration.
This was not not in your code.
The object structObj is a struct whose type is myStruct.
Now, your parameter stringy comes from another site, it is not lost.
But the struct structObj will have duration only inside your "free" function.
EDIT
I have fixed an error: the right declaration has to be "pointer to structObj", which is done in this way:
myStruct *structObj;
Observe that now myStruct is a non-initialized pointer, so the following assignment is legal:
structObj->stringy = stringy;
but will not work.
However I think this goes beyond the scope of the original question...
myStruct is type which you defined for your struct myStruct .that to you need to create an object before using.
you need to do like this:
typedef struct myStruct {
char *stringy;
} myStruct_t; //user defined data type
myStruct_t *obj;
// you need to allocate memory dynamically.
obj= (myStruct_t *) malloc(sizeof(myStruct_t));
usage:
scanf("%s",obj->stringy);
printf("%s",obj->stringy);
in function:
my_free(char *str) //str is local string
{
obj->stringy=str;
}
your can also try this code :
typedef struct myStruct {
char stringy[20]; //char *stringy
} myStruct_t; //user defined data type
myStruct_t obj; //object creation
usage:
scanf("%s",obj.stringy);
printf("%s",obj.stringy);
in function:
my_free(char *str) //str is local string
{
strcpy(obj.stringy,str);
}
You're correct that as soon as what it points to goes out of scope, it will point to garbage: this is a dangling pointer. You'll need to allocate some memory and perform a copy to fix this:
add_string(my_struct* s, const char* c)
{
size_t len = strlen(c);
s->file = malloc(len + 1);
strcpy(s->file, c);
}
Don't forget that you'll need to free it when you're done:
void destroy_struct(my_struct* s)
{
free(s->file);
free(s);
}
Code is as follows:
/* set.h */
struct setElement{
char *element;
setElement *next;
};
typedef struct setElement *Set; //Set is now the equivalent of setElement*
Set a;
setInit(&a);
/* setInit function declaration # setInit.c */
int setInit(Set *a){
(*a)->element = "asdf"; //results in a seg fault
}
Trying to malloc 'a' works, but if I try to access any member within the set 'a' doesn't work. I understand I'm passing a reference of the set from the main() function to setInit, so I believe the pointer contained within setInit is addressing the memory allocated by 'Set a' in the main() function, so a malloc wouldn't be required...
Iunno. Help is appreciated :)
The problem is that you have not allocated the setElement you are trying to assign to. In the main part of the code you are creating a Set, which is just a pointer to a setElement. This pointer is never set to point to anything sensible. I.e. you need something like
Set a = malloc(sizeof(setElement));
Alas, it is unclear where exactly your variables are defined. I assume your main.c is something like
#include "set.h"
Set a;
int main()
{
setInit(&a);
}
If so, your a, which is a pointer by itself, should point to somewhere.
If your framework wants malloc()ed data, you should do
int main()
{
a = malloc(sizeof(*a)); // *a is a struct setElement now, with 2 pointer-sized members.
setInit(&a); // Now seInit should be able to operate on the struct as wanted.
}
As #amaurea has mentioned, you'll need to make use of malloc() for your setElement structure. In addition to this, you need to do the same for the setElement struct's element member. A char* is merely a pointer to a char or char array and will not implicitly allocate anything.
int setInit(Set *a){
(*a)->element = "asdf"; //results in a seg fault
}
Could be re-written
int setInit(Set *a){
(*a)->element = malloc(sizeof("asdf"));
strcpy((*a)->element,"asdf");
}
Which the above could be rewritten to take a second parameter of the actual element contents.