This question already has answers here:
Changing address contained by pointer using function
(5 answers)
Does using calloc inside function, change the pointer passed as function argument
(2 answers)
Closed 5 years ago.
I am working with linked list in C, but I think didn't understant very well the use of pointers.
I have a structure for my linked list. I initialize the first element to NULL. I send this pointer to a function to create (with malloc) a new element of the list. But after the call of the function my element is still NULL. I don't understand. It is surely a stupid error but I need some help..
typedef struct Goto Goto;
struct Goto
{
int index;
Goto *next;
};
//my code
Goto* gotoList = NULL;
addLabel(gotoList, index);
// Here : gotoList is NULL
void addLabel(Goto* gotoList, int value) {
if (gotoList == NULL) {
Goto* gotoLabel = malloc(sizeof(*gotoList));
gotoLabel->index = value;
gotoLabel->next = NULL;
gotoList = gotoLabel;
}
else {
Goto* gotoLabel = gotoList;
Goto* newLabel = malloc(sizeof(*newLabel));
newLabel->next = NULL;
newLabel->index = value;
while (gotoLabel->next != NULL) {
gotoLabel = gotoLabel->next;
}
gotoLabel->next = newLabel;
}
// Here : gotoList is not NULL
}
Thanks for helping me
Well to make change either you have to pass the address of the variable from the caller function or return from the callee function the address of the allocated memory and assign it to respective variable.
Here you do neither of it so you don't get to retain the change.
By passing the adress of the variable you can do it like this:(The other can be done easily if you understand this one fully).
void addLabel(Goto** gotoList, int value) {
if (*gotoList == NULL) {
Goto* gotoLabel = malloc(sizeof(*gotoLabel ));
gotoLabel->index = value;
gotoLabel->next = NULL;
*gotoList = gotoLabel;
}
else {
Goto* gotoLabel = *gotoList;
Goto* newLabel = malloc(sizeof(*newLabel));
newLabel->next = NULL;
newLabel->index = value;
while (gotoLabel->next != NULL) {
gotoLabel = gotoLabel->next;
}
gotoLabel->next = newLabel;
}
}
Here what we did is simply passed the address of the variable. You will call the function like this
addLabel(&listhead,val);
One thing, you have a bad choice in selecting the names of the variables. Goto is the last choice of variable name. In C goto is a keyword, naming a variable on some variation of it is not only misleading but also erroneous in meaning too.
Related
My code doesn't adding second node to tree. It gives me SIGSEGV fault when i'm adding the second node.I think its about strcmp function but when i'm trying to understand how it works properly at the very bottom of main func it returns -1 so i've wrote it like this.And most of my variables named Turkish so here are the translations of them to make you understand more easily
dugum=node,kok=root;sol=left;sag=right;anne=mother
// C program to demonstrate insert operation in binary search tree
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct tree {
char *harf;
char *morskodu;
struct tree *left;
struct tree *right;
} agac;
agac *kok = NULL;
void ekle(char *harf, char *morskodu) {
if (kok == NULL) {
kok = (agac *)malloc(sizeof(agac));
kok->harf = harf;
kok->morskodu = morskodu;
kok->left = NULL;
kok->right= NULL;
} else {
agac *yeni = (agac *)malloc(sizeof(agac));
yeni->harf = harf;
yeni->morskodu = morskodu;
yeni->left = NULL;
yeni->right = NULL;
agac *dugum = kok, *anne;
while (dugum != NULL) {
anne = dugum;
if (harf <= dugum->harf)
dugum = dugum->left;
else
dugum = dugum->right;
}
if (harf <= dugum->harf)
anne->left = yeni;
else
anne->right = yeni;
}
}
void dolas(agac *dugum) {
if (dugum != NULL) {
printf(" %s ", dugum->harf);
dolas(dugum->left);
dolas(dugum->right);
}
}
void main() {
ekle("a", "-");
ekle("b", "-.");
dolas(kok);
int x = strcmp("A", "B");
printf("%d", x);
}
You try to dereference a NULL pointer.
while (dugum != NULL) {
anne = dugum;
if (harf <= dugum->harf)
dugum = dugum->sol;
else
dugum = dugum->sag;
}
This loop ends when dugum is NULL.
Directly after you try to access dugum->harf:
if (harf <= dugum->harf)
This leads to undefined behavior.
Also note that this comparisons compare the pointers to string literals, and is therefore also undefined behavior. To compare two C strings you should use strcmp.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I've been trying to work with structures, pointers and memory in C.
I have created this structure
typedef struct {
int id;
char *name;
} Object;
here is constructor
void object_ctor(Object *o, int id, char *name)
{
o->id = id;
o->name = malloc(sizeof(name));
if(sizeof(o->name)!=sizeof(name))
{
o->name=NULL;
}
else
{
strcpy(o->name, name);
}
}
here is decleration of o1
char tmp_name[] = "Hello 1";
Object o1;
object_ctor(&o1, 1, tmp_name);
here is destructor
void object_dtor(Object *o)
{
if(o->name != NULL)
{
free(o->name);
o->name = NULL;
}
}
printing object
void print_object(Object *o)
{
printf("ID: %d, NAME: %s\n", o->id, o->name);
}
calling copy
Object copy;
print_object(object_cpy(©, &o1));
and I´m trying create a copy of one structure to another (I have already constructed them).
Object *object_cpy(Object *dst, Object *src)
{
if(src!=NULL)
{
const size_t len_str=strlen(src->name)+1;
dst->name = malloc(10000000);
dst->id = src->id;
strncpy (dst->name, src->name,len_str);
}
if (strcmp(dst->name,src->name)!=0)
{
dst->name = NULL;
}
return dst;
}
But then when I'm trying to free both copy and original src I get a segmentation fault. I've been trying to run it through gdb and it said that I'm freeing same memory twice so I assume that the code for copying is wrong, but I don't know where.
And here is code that gives me segmentation fault
printf("\nCOPY EMPTY\n");
object_dtor(©);
o1.id = -1;
free(o1.name);
o1.name = NULL;
object_cpy(©, &o1);
print_object(©);
print_object(&o1);
I´m including these libraries
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
I'm using the std=c99 flag for to compile.
There is at least a problem here:
void object_ctor(Object *o, int id, char *name)
{
o->id = id;
o->name = malloc(sizeof(name));
if (sizeof(o->name) != sizeof(name))
{
o->name = NULL;
}
else
{
strcpy(o->name, name);
}
}
sizeof(name) is not the length of the string pointed by name. You need strlen(name) + 1 (+1 for the NUL terminator).
And your test if (sizeof(o->name) != sizeof(name)) is pointless, and I'm not sure what you're trying to achieve here.
You probably want this:
void object_ctor(Object *o, int id, char *name)
{
o->id = id;
o->name = malloc(strlen(name) + 1);
if (o->name != NULL)
strcpy(o->name, name);
}
There are similar problems in object_cpy:
pointless use of strncpy
pointless allocation of a 10Mb buffer
pointless test strcmp(dst->name, src->name)
You probably want this:
Object *object_cpy(Object *dst, Object *src)
{
if (src != NULL)
{
const size_t len_str = strlen(src->name) + 1;
dst->name = malloc(len_str);
if (dst->name != NULL)
{
dst->id = src->id;
strcpy(dst->name, src->name);
}
}
return dst;
}
With these corrections following code works fine:
int main()
{
char tmp_name[] = "Hello 1";
Object o1, copy;
object_ctor(&o1, 1, tmp_name);
object_cpy(©, &o1);
print_object(©);
print_object(&o1);
object_dtor(&o1);
object_dtor(©);
}
Event if this is not directly an answer to your problem, I'll give you how I organize my code in order to avoid memory problem like yours.
First, it all resolve around a structure.
To each structure, if needed, I do a "Constructor" and a "Destructor".
The purpose of the constructor is simply to set the structure in a coherent state. It can't never fail (implying that any code that could fail, like malloc, should not be in the constructor).
The purpose of the destructor is to clean the structure.
One little trick that I like to use is to put the constructor in a macro, allowing me to do something like 'Object var = OBJET_CONSTRUCTOR'.
Of course, it's not alway possible, it's up to you to be carreful.
For your code, it could be :
typedef struct {
int id;
char *name;
} Object;
#define OBJECT_CONSTRUCTOR {.id = -1,\ \\ Assuming -1 is relevant in your case, like an error code or a bad id value. Otherwise, it's useless.
.name = NULL}
void Object_Constructor(Object *self)
{
Object clean = OBJECT_CONSTRUCTOR;
*self = clean;
}
void Object_Destructor(Object *self)
{
free(self->name);
}
Here we go.
How to use it is simple : You always begin by the constructor, and you alway end by the destructor. That's why it's useless to set the char pointer "name" to NULL in the destructor, because it should not be used after by any other function that the constructor.
Now, you can have "initialisation" function. You can do a plain initialisation (it is your constructor function), or a copy initialisation, etc etc
Just keep in mind that the structure have been called into the constructor. If not, it's the developer fault and you do not have to take that in count.
A behavior that can be nice is, in case of error, to not modify the structure.
Either the structure is entierly modified in succes, or not at all.
For complex structure that can fail at many point, you can do that by "swapping" the result at the end.
void Object_Swap(Object *first, Object *second)
{
Object tmp = OBJECT_CONSTRUCTOR;
tmp = *fisrt;
*first = *second;
*second = tmp;
}
bool Object_InitByPlainList(Object *self, int id, consr char *name)
{
Object newly = OBJECT_CONSTRUCTOR;
bool returnFunction = false;
newly.id = id;
if (!(newly.name = strdup(name))) {
printf("error : %s : strdup(name) : name='%s', errno='%s'.\n", __func__, name, strerror(errno));
goto END_FUNCTION;
}
// Success !
Object_Swap(self, &newly);
returnFunction = true;
/* GOTO */END_FUNCTION:
Object_Destructor(&newly);
return (returnFunction);
}
It may be seem overcomplicated at the first glance, but that organization allow you to add more futur step "that can fail" cleanly.
Now, you can even do something this simply :
bool Object_InitByCopy(Object *dst, Object *src)
{
return (Object_InitByPlainList(dst, src->id, src->name));
}
All you have to do is to say in the documentation :
The first function to be called have to be "Object_Constructor"
After the "Object_Constructor", only the "Object_Init*" function can be called.
The last function to be call have to be "Object_Destructor"
That's all. You can add any "Object_*" function that you whant, like :
void Object_Print(const Object *self)
{
printf("ID: %d, NAME: %s\n", self->id, self->name);
}
Hope this organization will solve your memory problem.
An example :
int main(void)
{
Object test = OBJECT_CONSTRUCTOR;
Object copy = OBJECT_CONSTRUCTOR;
if (!Object_InitByPlainList(&test, 1, "Hello World !")) {
// The function itself has logged why it has fail, so no need to add error printf here
return (1);
}
Object_Print(&test);
if (!Object_Copy(©, &test)) {
return (1);
}
Object_Destructor(&test);
Object_Destructor(©);
return (0);
}
I have to copy paste this exact code below into 3 separate functions (juice function, milk function and buy function). So I thought, why not make another function called array_checker and call it in toe juice, milk and buy function instead of the copy pasting the code. However, the function (copy pasted code) needs to return 2 things. int item_used and int buy_now. How can I do this?
This is the code I copy paste:
if (item_sale == 1) {
item_used = TRUE;
buy_now = legal_cards[0];
} else {
item_used = FALSE;
}
There are two general approaches to this:
Create a struct with two int members to return from your function - this is fine when two values that you return are easy to copy, e.g. a pair of ints, or
Take a pointer for one or both variables - this lets you avoid copying, but requires the caller to allocate storage for the result upfront.
Here is an example of the first approach:
struct buy_decision {
int item_used;
int buy_now;
};
buy_decision milk(...) {
buy_decision res;
if (item_sale == 1) {
res.item_used = TRUE;
res.buy_now = legal_cards[0];
} else {
res.item_used = FALSE;
res.buy_now = 0;
}
return res;
}
Here is an example of the second approach with buy_now taken by pointer:
int milk(..., int* buy_now_ptr) {
if (item_sale == 1) {
*buy_now_ptr = legal_cards[0];
return TRUE;
}
return FALSE;
}
Well, you can return an array with both numbers.
To return multiple values from a function, create one structure, put the member whatever you want into this & return the structure variable. for e.g
typedef struct buy_fun_info {
int item_used;
int buy_now;
}BUY;
In array_checker() function, create the variable of above structure, fill the members & return those. for e.g
BUY array_checker() { /*array_checker() function */
BUY obj;
obj.buy_now = legal_cards[0];
obj.item_used = FALSE;
return obj;/* return structure variable */
}
Above I tried to explain with sample example, you need to modify accordingly.
You have to either define a structure to return :
struct itemStuff {
int itemUsed;
int buy_now;
}
then
struct itemStuff myItemFunction(...) {
struct itemStuff myItem;
(...)
if (item_sale == 1) {
myItem.item_used = TRUE;
myItem.buy_now = legal_cards[0];
} else {
myItem.item_used = FALSE;
}
return myItem;
}
The caller of the function will have to create the same struct to receive the return data
struct itemStuff thisItem = myItemFunction(...);
or use pass-by reference to pass in modifiable arguments
void myItemFunction(..., int *item_used, int *buy_noe) {
if (item_sale == 1) {
*item_used = TRUE;
*buy_now = legal_cards[0];
} else {
*item_used = FALSE;
}
}
Here, the caller will have to pass in the address of two integers to be set :
int used;
int buy;
myItemFunction(..., &used, &buy);
I had a homework where I should implement a list data type in C, done everything but the tests that the tutors gave us, aren't passing correctly, here you go (I'll explain what wrong in a min):
#define ASSERT_TEST(b) do { \
if (!(b)) { \
printf("\nAssertion failed at %s:%d %s\n",__FILE__,__LINE__,#b); \
return false; \
} \
} while (0)
the tests failing are:
after I create a list with 4 elements in it using listInsertLast, and I use this:
ASSERT_TEST(LIST_INVALID_CURRENT == listRemoveCurrent(list));
and after I create another list with 4 elements using listInsertLast and I use this:
ASSERT_TEST(listGetNext(list2) == NULL);
NOTE: I use these lines immediately after creating the list to check if the inner iterator status haven't changed after listInsertLast function, the thing is they should work, and the value returned by these 2 lines should be correct ( LIST_INVALID_CURRENT is enum value).. but they're not working, now I assume it's something that has to do with listInsertLast, they told us in the assignment we shouldn't change the inner iterator after adding at the end of the list, I tried everything possible, but still cant get them to work, my listInsertLast:
ListResult listInsertLast(List list, ListElement element) {
if (!list || !element) {
return LIST_NULL_ARGUMENT;
}
Node newElement = malloc(sizeof(*newElement));
if (!newElement) {
return LIST_OUT_OF_MEMORY;
}
newElement->data = list->copyElement(element);
if (listGetSize(list) > 0) {
Node save_iter = list->iter; // here?
list->iter = list->first;
while (list->iter->next) {
list->iter = list->iter->next;
}
list->iter->next = newElement;
list->iter = list->iter->next;
list->iter->next = NULL;
list->iter = save_iter; // and here ?
} else {
list->first = newElement;
list->first->next = NULL;
list->iter = list->first; // or maybe here ?
}
list->size++;
return LIST_SUCCESS;
}
What could the problem be, or if it has to do with other thing please help me..
Thank you very much <3
So I've got a weird problem and can't seem to solve it. I have an ADT called TEAM:
typedef struct Team {
char *name;
int points;
int matches_won;
int goal_difference;
int goals_for;
}TEAM;
I created a function to initialize variables of the TEAM* type with a given name:
TEAM *createTEAM (char *name){
int error_code;
if (name != NULL){
if(strcmp(name, "") != 0){
TEAM *new_team = (TEAM*)malloc(sizeof(TEAM));
new_team->name = (char*)malloc(sizeof(char)*strlen(name));
strcpy(new_team->name, name);
new_team->points = 0;
new_team->matches_won = 0;
new_team->goal_difference = 0;
new_team->goals_for = 0;
return new_team;
}else{
error_code = EMPTY_STRING_CODE;
}
} else {
error_code = NULL_STRING_CODE;
}
printf("Erro ao criar time.\n");
printError(error_code);
return NULL;
}
I also created a function to delete one of these TEAM* variables properly:
void deleteTEAM (TEAM *team_to_remove){
free(team_to_remove->name);
team_to_remove->name = NULL;
free(team_to_remove);
team_to_remove = NULL;
}
But when one or multiple test functions that I created (example below) run, the program sometimes crashes, sometimes doesn't. I've noticed that changing the names I use affects whether it crashes or not, even if they don't affect the test results.
int create_team_01(){
int test_result;
TEAM *Teste = createTEAM("Cruzeiro");
if (strcmp(Teste->name, "Cruzeiro") == 0){
test_result = TRUE;
}else test_result = FALSE;
_assert(test_result); //just a macro function that will check the argument and return 1 if it's false
deleteTEAM(Teste);
return 0;
}
I don't see any problems with memory allocation or freeing. Still, the debugger complains a lot about the first free() (can't find bounds) of the deleteTEAM function. Any ideas? Thanks a lot in advance for any help.
P.S.: I've even tried checking the mallocs' results, but it doesn't seem to be the problem either, so I removed it for the sake of simplicity.