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 :)
Related
this is driving me nuts, I've done my homework but for some reason here
for (int i = 0; i < room->num_of_challenges; i++) { // need a check
if (strcmp(room_to_enter, room->challenges[i].challenge->name) == 0) {
room->challenges[i].start_time = start_time;
room->challenges[i].visitor = malloc(sizeof(room->challenges[i].visitor));
room->challenges[i].visitor->current_challenge = malloc(sizeof(room->challenges[i].visitor->current_challenge));
*room->challenges[i].visitor->current_challenge = room->challenges[i];
*room->challenges[i].visitor->room_name = NULL;
*room->challenges[i].visitor->room_name = malloc(strlen(room_to_enter)+1);
strcpy(*room->challenges[i].visitor->room_name, room_to_enter);
inc_num_visits(room->challenges[i].challenge);
}
}
the program just crashes for some reason, at this point:
*room->challenges[i].visitor->room_name = malloc(strlen(room_to_enter)+1);
it's a 3 pages code with headers for each, and each page is about 300 line, so I can't post them all, also here are the structs:
struct SChallengeActivity;
typedef struct SVisitor
{
char *visitor_name;
int visitor_id;
char **room_name;
struct SChallengeActivity *current_challenge;
} Visitor;
typedef struct SChallengeActivity
{
Challenge *challenge;
Visitor *visitor;
int start_time;
} ChallengeActivity;
typedef struct SChallengeRoom
{
char *name;
int num_of_challenges;
ChallengeActivity *challenges;
} ChallengeRoom;
We can't edit the struct because it's given by the homework like that, the thing is I tried to set this line to NULL, like so:
*room->challenges[i].visitor->room_name = NULL;
and it still crashes at that line too, for some reason it can't reach that field in the struct.
Note: ignore the coding, I know I should check the malloc after each line, but for now I want it to work, I've been up all night to get it to work, and I couldn't, any help please ?
Thank you
When allocating memory for the visitor, you are only allocating the aize of a pointer. The visitor field inside your challenge is only a pointer to a Visitor. Thus you are not allocating enough memory. You should use:
malloc(sizeof(Visitor))
To get the real size of the Visitor structure and allocate ample space.
Also, setting pointers to null before allocating is useless. The call to malloc() will overwrite them.
Also,
*room->challenges[i].visitor->room_name = NULL;
room_name is a char** (pointer-to-pointer), which means it's still a pointer, and you dereference it before it's set.
Not sure why it needs to be a pointer-to-pointer, but if it needs to be, then you first have to allocate memory for one or more pointers (eg array):
room->challenges[i].visitor->room_name = malloc(sizeof(char*)*1);
*room->challenges[i].visitor->room_name = malloc(strlen(room_to_enter)+1);
...
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 (&))
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.
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. :)
typedef struct Model
{
int recordId;
char *name;
}Model;
typedef struct ModelArray
{
//keeps the size that the array was initially create with. When more elements are needed
//we use this to add that many more elements
int originalSize;
//total number of elements that can be used
int elements;
//total number of elements used
int count;
//the actual array is stored here
Model *source;
}ModelArray;
void initModelArray(ModelArray *array, int numberOfElements)
{
array->originalSize = numberOfElements;
array->elements = numberOfElements;
array->count = 0;
array->source = malloc(sizeof(Model)*numberOfElements);//0 bytes in 3 blocks are definitely lost in loss record 1 of 65
}
void deallocModelArray(ModelArray *array)
{
if(array == NULL)
return;
array->elements = 0;
array->count = 0;
free(array->source);
array->source = NULL;
free(array);
}
main(int argc, const char * argv[])
{
ModelArray *models = malloc(sizeof(ModelArray));
initModelArray(models, 10);
deallocModelArray(models);
}
What is lost? Code looks fine to me. I'm sure I could say array->source = NULL first but it's not needed, right?
To deallocate these structures correctly, you need to do the following, in this order:
free(models->source);
free(models);
If you do anything else, you're leaking memory.
Edit:
OK, having seen the Model struct, you're probably leaking the names, or at least valgrind thinks you do because you deallocate the ModelArray structure, which contains a pointer to a Model structure, which contains a char* which you don't free first.
So:
int i;
for( i=0; i<models->originalSize; i++ ) {
if( models->source[i]->name != NULL ) {
free( models->source[i]->name );
}
}
free(models->source);
free(models);
And it would be a good idea to use calloc() instead of malloc() when allocating models->source in the first place. This will set all the name pointers to 0. Without this, the test for models->source[i]->name being non-NULL above might fail if name happens to contain some garbage (since using uninitialized memory produces undefined behavior.)
Er... Yes, the memory is lost. Of course, it is lost, since you "left out dealloc code"!
How could you possibly expect anyone to answer your question when you "left out dealloc code"? The very essence of your question is whether your dealloc code is correct or not. And you decided to leave it out?
On top of that, there quite a few thing that make little sense in your code. What is
typedef struct ModelArray {
...
Model *source;
...
} Model;
supposed to mean? Why are you typedefing struct ModelArray as Model? In fact, your code will not even compile, since Model * is used inside the struct, where it is not declared yet. You also use ModelArray type in your code, while in reality there's no such type. You have struct ModelArray, but not just ModelArray. The code you posted is not real code. Post real code, please. (Apparently it was supposed to be typedef struct ModelArray { ... } ModelArray; with Model defined elsewhere.)
Finally, as an unrelated note, // comments is a C99 feature. In C99 the function return type cannot be omitted (no "implicit int" rule in C99), meaning that you have to declare your main function as int main.