char* value changing after use of fgets - c

so my first question would be. Does fgets overwrite other char* values?
Otherwise, I'm not really sure how I have messed up my mallocs. Below is the code where the value is changing. First line is where the variable is being created.
data[dataIndex++] = createVariable(varName, 1, value, -1, line, NULL);
The code where the variable is being created
Variable *createVariable(char *name, int type, int val, int len, int line, char *string)
{
Variable *var = malloc(sizeof(Variable));
var->name = name;
var->setting = type;
var->num = val;
var->length = len;
var->line = line;
var->string = string;
return var;
}
What data looks like and how it was created.
Variable **data;
data = malloc(4 * sizeof(Variable *));
Forgot to add this, but below is my fgets code
if (fgets(line, MAX_LINE_LENGTH, in) == NULL)
{
break;
}

The problem is this line in your createVariable function:
var->name = name;
What this does is copy the pointer given as the first argument to the name field in the var structure; it doesn't make a (separate) copy of the data that is pointed to! So, assuming you call createVariable many times with the same variable as the first argument, then every object created will have the same address in its name field, and any modifications you make to any of them (via fgets) will change all of them.
To get round this, you need to allocate new memory for the name field, each time you call the createVariable function, then copy the string data to it. The simplest way to do this is using the strdup function:
Variable *createVariable(char *name, int type, int val, int len, int line, char *string)
{
Variable *var = malloc(sizeof(Variable));
var->name = strdup(name);
//...
var->string = strdup(string);
//...
But note, you will now need to be sure to free that memory from each object when you (eventually) delete it. Something like this:
void deleteVariable(Variable** var)
{
free((*var)->name); // free the name memory
free((*var)->string); // free the string memory
free(*var); // free the actual structure
*var = NULL; // set the pointer to NULL - to prevent multiple frees
}
EDIT: Just re-read your question, and noticed that you are making the same mistake with the string field! The same fix needs to be applied to that!

Related

C - Unable to copy a string in a function

This function is to split string based on \n and see if the row number is selected. If the row number matched, this string should be copied and used by other function:
void selectDeparment(char* departments, int selectedNum, char* selectedDepartment){
char* copyOfDepartments = malloc(strlen(departments)+1);
strcpy(copyOfDepartments,departments);
char* sav1 = NULL;
char* token = strtok_s(copyOfDepartments,"\n",&sav1);
int counter = 0;
while(token != NULL){
if(counter == selectedNum){
selectedDepartment = malloc(strlen(token)+1);
strcpy(selectedDepartment,token);
}
++counter;
token = strtok_s(NULL, "\n", &sav1);
}
}
This function is called in main like:
char* selectedDepartment;
selectDeparment(recordsPtr[0], 1, selectedDepartment);
printf(selectedDepartment);
recordsPtr[0] contains four strings with \n at the end:
aDeparment
anotherDepartment
newDepartment
otherDepartment
In C, we are encouraged to use pointer to get a value from function instead of returning a string from a function. However, the prinft in main function gives random output
I believe there is some confusion in the way you are using pointers here. Let me clarify.
In the main function, the character pointer selectedDepartment holds a certain memory in the computer. But when a function call is made to void selectDeparment(char* departments, int selectedNum, char* selectedDepartment), a new copy of selectedDepartment is created. Henceforth any changes which are made to selectedDepartment are done only at the scope of the called function and does not impact the original pointer in the main function.
Thus one clear way to solve this problem will be to pass a pointer to the character pointer defined in the main function. This will then give the correct/expected results.
Here is the modified version of the function -
void selectDeparment(char* departments, int selectedNum, char** selectedDepartment){
char* copyOfDepartments = malloc(strlen(departments)+1);
strcpy(copyOfDepartments,departments);
char* sav1 = NULL;
char* token = strtok_s(copyOfDepartments,"\n",&sav1);
int counter = 0;
while(token != NULL){
if(counter == selectedNum){
(*selectedDepartment) = malloc(strlen(token)+1);
strcpy(*selectedDepartment,token);
}
++counter;
token = strtok_s(NULL, "\n", &sav1);
}
}
And this is how it is called from the main function -
int main() {
char* recordsPtr[] = {"aDeparment\nanotherDepartment\nnewDepartment\notherDepartment"};
char* selectedDepartment;
selectDeparment(recordsPtr[0], 1, &selectedDepartment);
printf(selectedDepartment);
}
I think you are getting confused with the "A Pointer To What?" you are supposed to return. In your selectDeparment() function, if I understand what is needed, is you simply need to return a pointer to the correct department within recordsPTR. You do not need to allocate or tokenize to do that. You already have the index for the department. So simply change the return-type to char * and return departments[selectedNum];.
For example, you can whittle-down your example to:
#include <stdio.h>
char *selectDeparment (char **departments, int selectedNum){
return departments[selectedNum];
}
int main (void) {
char *selectedDepartment = NULL;
char *recordsPTR[] = { "aDepartment\n",
"anotherDepartment\n",
"newDepartment\n",
"otherDepartment\n" };
selectedDepartment = selectDeparment (recordsPTR, 1);
fputs (selectedDepartment, stdout);
}
Note: the '*' generally goes with the variable name and not the type. Why? Because:
int* a, b, c;
certainly does NOT declare three-pointers to int,
int *a, b, c;
makes clear that you have declared a single-pointer to int and two integers.
Example Use/Output
Running the example above you would have:
$ ./bin/selectedDept
anotherDepartment
You will want to add array bounds protection to ensure the index passed does not attempt to read past the array bounds. That is left to you.
If You Must Use void
If you must use a void type function, then you can pass the Address Of the pointer to the function so the function receives the original address for the pointer in main(). You can then assign the correct department to the original pointer address so the change is visible back in main(). When you pass the Address Of the pointer, it will require one additional level of indirection, e.g.
#include <stdio.h>
void selectDeparment (char **departments, int selectedNum, char **selectedDeparment) {
*selectedDeparment = departments[selectedNum];
}
int main (void) {
char *selectedDepartment = NULL;
char *recordsPTR[] = { "aDepartment\n",
"anotherDepartment\n",
"newDepartment\n",
"otherDepartment\n" };
selectDeparment (recordsPTR, 1, &selectedDepartment);
fputs (selectedDepartment, stdout);
}
(same result, same comment on adding array bounds protection)
Look this over and let me know if I filled in the missing pieces correctly. If not, just drop a comment and I'm happy to help further.

Losing contents of char**array when passed to function in C

I have the following structs in my on-going struggle to eventually create some kind of shell (based eventually around execvp().
struct commands {
char cmdname[30]; // The name of the command
enum ActionType action; /* char action[30]; what action to take */
};
struct userinput {
struct commands theaction; //The chosen action
char cmdentered[100]; // The cmd entered
char **anyargs; //The tokenised command
int argcount; //Argument count
};
And I initialise anyargs using malloc and create an array of strings with one string per argument to be passed on to the execvp.
I then get user input, convert the input into tokens stored in anyargs and examine the strings to find out what sort of action needs to be taken and store that in an enum.
All these methods are done by passing the pointer to the struct userinput as method parameters - which works fine. HOWEVER when I pass the pointer to the struct to a nested function, the char** anyargs becomes empty.
I hope the code I've added provides a solution to the answer! On another observation - when passed to a function inside a function, the actual value of the pointer doesn't change - only the dereferenced contents of the pointer.
Any help would be most gratefully received! I've tried to strip the code down to the areas I think are causing the issue!
Thank you!
int main() {
struct commands cmdlist[4]; //Array of structures with all commands in them
memset(cmdlist, 0, sizeof(cmdlist));
struct userinput userentry = { { { 0 } } }; //Structure containing input
userentry.theaction = cmdlist[0]; //Initialize empty command
userentry.anyargs = calloc(100, sizeof(char));
runEntry(&userentry, cmdlist); //Pass struct to function
free(userentry.anyargs);
return 0;
}
int runEntry(struct userinput *userentry, struct commands thecmds[]) {
int retval = 0;
int childpid = 0;
int processStatus;
printf("\n ... running cmd: \n\n");
printUserEntry(userentry); //in printUserEntry,
//userentry->anyargs[0] = NULL - why?
}
You've allocated 100 bytes worth of char * elements in anyargs. You haven't initialized those pointers, though. The fact that anyargs[0] happens to contain NULL is nice, but not guaranteed. malloc() doesn't initialize the allocated space.
In other words, when you say:
userentry.anyargs = malloc(100);
you've created:
userentry.anyargs = {
???, // uninitialized char *
???, // and another
???, // and another
...
??? // (100 / sizeof(char *)) entries later
};
You can explicitly initialize those to NULL in a loop:
for ( i = 0; i < (100 / sizeof(char *)); ++i )
userentry.anyargs[i] = NULL;
(or use calloc() instead of malloc() to ensure everything is zeroed out).
or you can allocate some space to them:
for ( i = 0; i < (100 / sizeof(char *)); ++i )
userentry.anyargs[i] = malloc(50); // or some other length
or just set them directly in runEntry():
userentry.anyargs[0] = "foo";
userentry.anyargs[1] = strdup(something);

Reused Address Space in C?

In a part of the program I'm working on I assign a name differently in different circumstances, but I want to keep the name either way, obviously. So I did something like so:
char *name;
if(*condition one*){
char namebuilder[30] = "";
//fill char array here
name = namebuilder;
} else {
name = info->name; //a char* from a struct
}
char otherstring[30] = "______________________________"
So basically the problem I'm having is that when the function takes the else route name sticks around and works just fine. But when it makes namebuilder and constructs the name, for some reason otherstring is ending up in the same address as name, and the name is getting overwritten with "__________________________". I don't understand why this is happening or how I can prevent it.
P.S: I've tested it by printing the addresses of name and otherstring, and they have the same address stored in them, but only if namebuilder was used.
Extra Background: this is a little program I'm making to mess around with pthreads, so it could possibly have to do with threading I guess, but none of the variables I mentioned are global.
EDIT: Here's the actual code for those of you asking.
struct thread_data
{
char *name;
int max;
};
void* race(void* params)
{
struct thread_data* info;
info = (struct thread_data*)params;
int len = strlen(info->name);
char* name;
if(info->max > len){
int i;
char newname[30] = "";
for(i = 0; i < info->max-1; i++){
if(i < len){
newname[i] = info->name[i];
} else {
char nextchar = randChar();
newname[i] = nextchar;
}
}
newname[info->max] = '\0';
name = newname;
} else {
name = info->name;
}
pthread_mutex_lock(&locker);
printf(name); //This correctly prints the name either way.
printf(" takes off!\n");
pthread_mutex_unlock(&locker);
//begin trying to spell here.
int spelt = 0;
char spelling[30] = "______________________________";
// All code after this sees name as "______________________________" only if it came
// from the if statement and not the else.
namebuilder was stored in the stack because it's local inside the if statement, after exiting the condition, it was marked as free, so when declaring otherstring, which have the exact same type and memory use as namebuilder, it took its place in the stack.
Here's how you can fix it:
char *name;
char namebuilder[30] = "";
if(*condition one*){
//fill char array here
name = namebuilder;
} else {
name = info->name; //a char* from a struct
}
char otherstring[30] = "______________________________";
Namebuilder is local to the if block. You need to lift it one scope up, or allocate it in dynamic memory with malloc() (don't forget to free() it when you're done !)
Your namebuilder is local to the if block. Which means that once you leave that and try to use your name, accessing the memory name points at now is UB. You'll either have to dynamically allocate the memory for namebuilder - which means you'd have to remember to clean it up later on - or you'd have to lift the declaration of namebuilder to the scope where it's being used.

Freeing memory, functions

I am trying to free some memory that I allocated in one functions in another function. An example of this would be:
MusicRec * createRecord(char * title, char * artist, double fileSize, int length, char theType)
{
MusicRec * newRecord;
MusicRec * next;
newRecord = malloc(sizeof(MusicRec));
newRecord->title = malloc(sizeof(char)*(strlen(title))+1);
strcpy(newRecord->title, title);
newRecord->artist = malloc(sizeof(char)*(strlen(artist))+1);
strcpy(newRecord->artist, artist);
newRecord->sizeInKB = fileSize;
newRecord->lengthInSeconds = length;
newRecord->type = theType;
newRecord->next = NULL;
next = NULL;
return(next);
}
I have malloced memory in that function, but now i am trying to free this malloced memory in a different function such as my main function. How would i do this?
Just use the corresponding deallocation function free() Remember you cannot use already deallocated memory at all.
Some points to consider:
Better change how you allocate memory, so you can more easily change the type:
Was: newRecord = malloc(sizeof(MusicRec));
Should be: newRecord = malloc(sizeof *newRecord);
Consider defining some helper functions for things you often do. Example (this function is often actually already defined):
Was: newRecord->title = malloc(sizeof(char)*(strlen(title))+1);strcpy(newRecord->title, title);
Should be: newRecord->title = strdup(title);
Never use sizeof(char): It looks illiterate, because you are literally asking: How many char's do I need to save one char?
For cases it's not defined:
char* strdup(const char* str) {
size_t len = strlen(str) + 1;
char* ret = malloc(len);
memcpy(ret, str, len);
return ret;
}
If you have passed that variable as reference from another function then you can free that variable from that function using free() function; otherwise you can not free that variable from another function if you have passed by value.

how to create a dynamic array of structs in C

I want to send a struct of symbol from one function to other functions, and i want to create an array that every cell will point to a different values of the following struct:
typedef struct symbol_def
{
char* sym_name;
char* sym_type;
unsigned short sym_address;
char sym_is_ext;
}symbol;
I'm trying to run this code:
//function-1
void compile_input_file(char* input)
{
symbol* curr_symbol;
//Intalize curr_symbol struct
curr_symbol = (symbol*)malloc(sizeof(symbol));
//memset((void)curr_symbol, 0, sizeof(symbol));
parse_command(line, &parser, curr_symbol, &index);
}
//function-2
void parse_command(char* line, parse_params* parser, symbol* curr_symbol, int* index)
{
sym = symbol_table_create(curr_symbol, "directive", sym_label, '0', index);
}
//function-3
symbol* symbol_table_create(symbol* curr_symbol,char* s_type, char* label, char is_ext, int* index)
{
int temp = *index;
curr_symbol = (symbol*)realloc(curr_symbol,sizeof(symbol*)*(temp+1));
curr_symbol[temp].sym_type = s_type;
curr_symbol[temp].sym_name = label;
curr_symbol[temp].sym_address = 0;
curr_symbol[temp].sym_is_ext = is_ext;
temp++;
*index = temp;
return curr_symbol;
}
The problem is that the curr_symbol gets override all the time.
my purpose is to build a table of symbols, that in every iteration on the code i'll add another cell to the array
any ideas?
There is a problem, with the realloc It should be curr_symbol = (symbol*)realloc(curr_symbol,sizeof(symbol)*(temp+1)); You were actually allocating it sizeof pointer which is 4 Bytes.
A Piece of Advice Realloc is a costly operation you should use it only if necessary and not on every instance
you could malloc in function3 instead of function1. If you do so you dont even need to pass the pointer via function2.
or else put a check to see if realloc is really necessary or not. Eg:- Check if the pointer is allocated memory. if(ptr!=null){ //realloc } This can work as a checking case too.
Best of Luck. :)

Resources