Reused Address Space in C? - 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.

Related

char* value changing after use of fgets

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!

C: How to free a struct ** that contains fields which are char* and ENUM (int)?

My code contains the struct BeforeTriag which is from type Patient** .
here is the structs and it's fields:
typedef struct{
char Id[ID_SIZE];
char Name[NAME_SIZE];
char LastName[NAME_SIZE];
char PhoneNum[PHONE_SIZE];
STATUS Status;
char Address[ADDRESS_SIZE];
}Patient;
Here is my initilization and allocation:
Patient** BeforeTriag = NULL;
int* BeforeTriagSize[1] = { 0 };
BeforeTriag = (Patient**)malloc(sizeof(Patient*));
if (!(BeforeTriag))
{
printf("ERROR!Out of memory!");
exit(1);
}
*BeforeTriag = (Patient*)malloc((PatientArraySize)* sizeof(Patient));
if (!(*BeforeTriag)){
printf("ERROR!Out of memory!");
exit(1);
}
here i'm tring to free each field in the struct:
for (i = 0; i < (*BeforeTriagSize); i++){
free((BeforeTriag)[i]->Id);
free((BeforeTriag)[i]->Name);
free((BeforeTriag)[i]->LastName);
free((BeforeTriag)[i]->Address);
free((BeforeTriag)[i]->PhoneNum);
}
free(BeforeTriag);
When I am debugging it crush on the first row of the free id:
free((BeforeTriag)[i]->Id);
What should i do to free as proper?
The individual fields within BeforeTriag[i] were not dynamically allocated by themselves, so you can't free them. You need to free the struct as a whole, because that's what was allocated:
for (i = 0; i < (*BeforeTriagSize); i++){
free(BeforeTriag[i]);
}
free(BeforeTriag);
You do not have to do this:
for (i = 0; i < (*BeforeTriagSize); i++){
free((BeforeTriag)[i]->Id);
free((BeforeTriag)[i]->Name);
free((BeforeTriag)[i]->LastName);
free((BeforeTriag)[i]->Address);
free((BeforeTriag)[i]->PhoneNum);
}
Because they are not dynamically allocated.
But you have to free BeforeTriag[i] inside the loop.
for (i = 0; i < (*BeforeTriagSize); i++){
free(BeforeTriag[i]);
}
free(BeforeTriag);
While #dbush and #RolBrok already pointed out correctly that there's no need to free the individual members, there is another bug in your code:
int* BeforeTriagSize[1] = { 0 };
This line initalizes a int ** to zero. I'm not really sure why you want this variable to be in an array, but anyway, the correct way to declare it would be
int BeforeTriagSize[1] = { 0 };
(If you only need one value for BeforeTriagSize anyway, just declare it as an int!)
Edit:
Another thing you should look closer into is the way you're allocating memory for your structs:
*BeforeTriag = (Patient*)malloc((PatientArraySize)* sizeof(Patient));
With this you're always writing to the same pointer. So when you are allocating the memory for the second struct, you are overwriting the position of the first one, basically causing a memory leak.
Consider something along the line of
BeforeTriag[BeforeTriagSize++] = (Patient*)malloc((PatientArraySize)* sizeof(Patient));
This ensures that you are writing to a new position in your array every time. (Assuming you changed BeforeTriagSize to an int - if you need to hand it over as a pointer to some functions just use the address operator (&))

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);

How to return an array in without storing globally?

I have utitlity function which gives me a char buffer of individual bytes, when I provide it with a structure.
unsigned char complete[16] = { 0 };
char* construct_complete_array(socketType* m)
{
unsigned char *temp = (unsigned char*) m;
size_t j;
for (j = 0; j < sizeof(*m); j++)
{
complete[j] = *(temp);
printf("%.2x ", *(temp));
*temp++;
}
return complete;
}
int diff_bit_calc(socketType* datanode, socketType* knode)
{
char* result = construct_complete_array(datanode);
size_t j;
printf("\nPrinting result: \n");
for (j = 0; j < sizeof(*datanode); j++)
{
printf("%.2x ", *(result));
*result++;
}
}
I want it to be a generic function which when provided with a structure will return me a char buffer of the structure.
I might have another invocation like
char* result1 = construct_complete_array(knode);
(I don't think having complete[16] buffer as global a good idea. Having it local and returning it is still a worser idea. )
In general, you can't do that without dynamically allocating memory. Most people get around it by declaring the buffer in the calling function and passing that buffer to a function, which will then fill in the passed buffer.
In your specific case, I'm not so sure a function is necessary; it's rather short to do it inline, e.g.:
/* to get the bytes representing `something' into a char array */
char something_chars[sizeof(something)];
memcpy(something_chars, &something, sizeof(something));
As for as I know, there are two ways to do that.
Since the return value of the function is a pointer, so you must make sure that the memory you store result won't be destroyed. Other than using global variable, you can use dynamic allocating memory(like icktoofay said) or static keyword
(like Tay Wee Wen said).
When using dynamic allocating memory, the user of this function should remember to free() outside the function.
When using static keyword inside the block, there is a problem of overriding. If you call the function several times, only the last return value was kept.
By the way, *temp++; is a little strange, why not use temp++; instead.
Declare the array static inside the function.
char* construct_complete_array(socketType* m){
static unsigned char complete[16]= {0};
unsigned char *temp = (unsigned char*)m;
size_t j;
for (j = 0;j<sizeof(*m);j++){
complete[j] = *(temp);
printf("%.2x ", *(temp));
*temp++;
}
return complete;
}
You'd have to change your interface a bit:
char* construct_complete_array(socketType* m, char temp[]);
then on the calling side you can use a compound literal to provide temp
char* result = construct_complete_array(datanode, (char[sizeof *datanode]){ 0 });
If you have to repeat that in several places you could put that into a macro
#define CONSTRUCT_ARRAY(X) construct_complete_array((X), (char[sizeof *(X)]){ 0 })
so then again your call side looks almost as you had it before
char* result = CONSTRUCT_ARRAY(datanode);
For this to work you just have to have in mind that the value in result points to local data with the same life time as result itself.

Overwriting array of structs in C

I'm trying to pass a pointer to an array of structs to a function. Then have the function create its own array of structures, populate it with data and then overwright the the old array with the new array.
I'm pretty sure the problem is with occurring when I try to overwrite the memory. I think that I could be either using the wrong method to overwrite the memory(should I be using the memory functions?) or I might be trying to overwrite the wrong thing. I'm not quite sure what I'm doing wrong. If someone could point me in the right direction I would be extremely thankful; I've been pulling the hair out of my head for like three hours now.
Struct:
typedef struct
{
char command;
int argc;
char* argv[];
}cmd;
Code:
int main(int argc, char *argv[])
{
[... irrelevant code]
cmd cmdv[count];
cmd* cmdv_ptr = &cmdv[0];
dissectCmd(cmdstr, cmdv_ptr);
printf("%i", cmdv[0].argc);
return 0;
}
void dissectCmd(char* str, cmd* cmdv)
{
[... irrelevant code]
cmd cmds[count];
int i = 0;
for(i = 0; i < count; i++)
{
cmd next;
next.command = 'u';
next.argc = 100;
cmds[i] = next;
}
cmdv = cmds;
}
You're not overwriting the memory -- the statement cmdv = cmds just copies the pointer (making cmdv point at cmds.) If you want to actually copy the memory, you need memcpy(cmdv, cmds, count * sizeof(cmd));
i'm not sure about this, but try declaring
void dissectCmd(char* str, cmd* cmdv)
as
void dissectCmd(char* str, cmd** cmdv)
changing
cmdv = cmds;
to
(*cmdv) = &cmds;
and changing current call from main which is now
dissectCmd(cmdstr, cmdv_ptr);
to
dissectCmd(cmdstr, &cmdv_ptr);
also, when you do this, you loose the address to the old array completely, creating a memory leak. unless you already free that memory in your second [... irrelevant code] passage :)

Resources