Uninitialized or NULL pointer in array of pointers - c

I have an array of pointers to structs.
struct key {
int *data;
};
struct key *entry = NULL;
entry = malloc(sizeof(entry));
Reallocated a bit of times:
node = realloc(node, (length+1)*sizeof(node[0]));
node[length].data = some_int;
In another part of my program, I want to iterate through it. I don't know how much elements it is containing at the moment.
for (i=0; &(node[i]) != NULL; i++)
length = i;
But I have infinity loop. Because:
(gdb) p node[i]
$1 = {data = 0x0}
It seems to like an uninitialized value, but it is not NULL pointer.
How to determine the end of an array?
Why it is not NULL pointer?

&(node[i]) takes the address of node[i].
So
&(node[i]) != NULL
will always be true, as the address of node[i] will always be different from NULL.

&(node[i]) is same as node + i and as long as node is not null and i is not zero, this will be non-null.
If you want to mark end of array, I would suggest always (re)allocate one extra element and initialize pointer member of termination with NULL.
struct key *temp = realloc(node, (length+2)*sizeof(node[0]));
if(NULL == temp) { /* Updated as per suggestion from #alk */
/* Handle error and return */
}
node = temp;
node[length].data = address_of(some_int);
node[length+1].data = NULL;
And later while looping
for (i=0; node[i].data != NULL; i++)
length = i;
But an even better solution would be to keep length you last used to realloc bundled with node. This way you won't need to calculate it using a loop.

Related

linked list using only pointers question+problem

I face annoying problem I do not quite understand ,
I have pointers of type int *
example code:
int* p_Memory_blocks;
int MemoryInit(int num_of_blocks, int block_size) {
int* head;
head = NULL;
for (int i = 0; i < num_of_blocks; i++) {
if ((head = malloc(block_size)) == NULL) {
printf("allocating memory failed");
for (int j = 0; j < i; j++) {
p_Memory_blocks = head;
head = *head;
free(p_Memory_blocks);
}
return 1;
}
head = &p_Memory_blocks;
p_Memory_blocks = head;
}
return 0;
}
int* MyMalloc() {
int* return_block = p_Memory_blocks;
p_Memory_blocks = *p_Memory_blocks;
return return_block;
}
void MyFree(int* block) {
*block = p_Memory_blocks;
p_Memory_blocks = block;
}
thats the code for initializing my pool for memory trying to connect the pointer to a linked pointer somehow
basically Im using pointers to build linked pointers
(my assignment is to build a fixed block memory pool allocator , I can only malloc the total amount of block_size * block_amount in bytes ,and I cannot use any more mallocs for any manager , the only thing I have is a global variable of type int * so i wanted to build a linked pointers and return the head to the user and then advance it to the next pointer)
in theory the p_Memory_blocks should advance to the last value because like linked list he is the head currently but the I get 'Unhandled exception thrown: read access violation.' and such
if fails after using twice
p_Memory_blocks = *p_Memory_blocks;
,so anyone got an explanation ? or a better way to implement it?
thank you very much !
Ive tried to malloc more memory , and variable types
A linked list node has two fields: next and value. You're not going to get far with just one field. Until you address this, you are doomed to fail.
Your immediate problem stems from this.
In your loop, n1 sometimes contains a pointer to the next node, and it sometimes contains a value, and you have no way to tell the two apart.
In technical terms, n1 will eventually hold 100, at which point *n1 results in undefined behaviour.
You need to address the issue that your structure does not contain enough information before you can proceed.

Simulating a List with array

Good morning!
I must handle a struct array (global variable) that simulates a list. In practice, every time I call a method, I have to increase the size of the array 1 and insert it into the new struct.
Since the array size is static, my idea is to use pointers like this:
The struct array is declared as a pointer to a second struct array.
Each time I call the increaseSize () method, the content of the old array is copied to a new n + 1 array.
The global array pointer is updated to point to a new array
In theory, the solution seems easy ... but I'm a noob of c. Where is that wrong?
struct task {
char title[50];
int execution;
int priority;
};
struct task tasks = *p;
int main() {
//he will call the increaseSize() somewhere...
}
void increaseSize(){
int dimension = (sizeof(*p) / sizeof(struct task));
struct task newTasks[dimension+1];
for(int i=0; i<dimension; i++){
newTasks[i] = *(p+i);
}
free(&p);
p = newTasks;
}
You mix up quite a lot here!
int dimension = (sizeof(*p) / sizeof(struct task));
p is a pointer, *p points to a struct task, so sizeof(*p) will be equal to sizeof(struct task), and dimension always will be 1...
You cannot use sizeof in this situation. You will have to store the size (number of elements) in a separate variable.
struct task newTasks[dimension+1];
This will create a new array, yes – but with scope local to the current function (so normally, it is allocated on the stack). This means that the array will be cleaned up again as soon as you leave your function.
What you need is creating the array on the heap. You need to use malloc function for (or calloc or realloc).
Additionally, I recomment not increasing the array by 1, but rather duplicating its size. You need to store the number of elements contained in then, too, though.
Putting all together:
struct task* p;
size_t count;
size_t capacity;
void initialize()
{
count = 0;
capacity = 16;
p = (struct task*) malloc(capacity * sizeof(struct task));
if(!p)
// malloc failed, appropriate error handling!
}
void increase()
{
size_t c = capacity * 2;
// realloc is very convenient here:
// if allocation is successful, it copies the old values
// to the new location and frees the old memory, so nothing
// so nothing to worry about except for allocation failure
struct task* pp = realloc(p, c * sizeof(struct task));
if(pp)
{
p = pp;
capacity = c;
}
// else: apprpriate error handling
}
Finally, as completion:
void push_back(struct task t)
{
if(count == capacity)
increase();
p[count++] = t;
}
Removing elements is left to you – you'd have to copy the subsequent elements all to one position less and then decrease count.

Allocating array of struct with array inside

I want to read users input combined of strings and numbers, like this:
50:string one
25:string two blablabla
...
I don't know how many of the lines the input will have and I also don't know maximum length of the strings.
So I created
typdedef struct line
{
int a
char *string
} line;
Then an array of this sturct
line *Array = NULL;
Now I have a cycle, that reads one line and parses it to temporaryString and temporaryA. How can I realloc the Array to copy these into the array?
There are two valid options to do what you want:
1) use the realloc() function; it's like malloc and calloc but you can realloc your memory, as the name can advise;
2) use a linked list;
The second is more complex than the first one, but is also really valid. In your case, a simple linked list could have the form:
typdedef struct line
{
int a;
char *string;
line *next;
//line *prev;
} line;
Everytime you add a node, you have to alloc a struct line with your new data, set next pointer to NULL or to itself, it's the same, and set the previous next pointer to the new data you created. That's a simpy method to do manually a realloc. The prev pointer is needed only if you need to go from the last item to the first; if you don't need this feature, just save the root pointer (the first one) and use only next pointer.
You could something like this (pseudo code).
idx = 0;
while (input = read()) {
temporaryString, temporaryA = parse(input);
Array = realloc(Array, (idx + 1)*sizeof(line));
Array[idx].a = temporaryA;
Array[idx].string = malloc(strlen(temporaryString) + 1);
strcpy(Array[idx].string, temporaryString);
idx++;
}

Unsual Result when passing pointer as argument

I have implemented a hashmap.
struct hashmap_elmnts
{ char *key;
int in_use;
void *data; //contains the address of the malloc of struct ussd defined below
};
struct hashmap_map
{
int table_sizel;
int size;
struct hashmap_elmnts *element ;
};
Now, I have another structure USSD
typedef struct ussd { char menu;
int8_t did;
int8_t invokeid;
char *language;
char *msisdn;
char *ussd_string;
} USSD;
Now, while inserting in the HASHMAP,
USSD *init = (USSD*)malloc(sizeof(USSD));
init->msisdn = (char*)malloc(sizeof(char));
init->language = (char*)malloc(sizeof(char));
init->ussd_string = (char*)malloc(sizeof(char));
msisdn = language = ussd_string = NULL;
Then, I assign some values and then insert in the hashmap
However, while getting the information back, i face some issue:
IN FILE GET.c
I call a function
USSD *pointer = NULL;
res = hashget(key, pointer);
if (pointer == NULL)
printf ("pointer fail\n");
else
printf ("pointer pass\n");
IN FILE HASHGET.c
int hashget(int key, USSD_STRUCT *arg)
{
/** declaring a hashmap_map pointer **/
struct hashmap_map *m;
now, after various calculation -> i find a value of 'curr'
arg = (m->element[curr].data);
if (arg == NULL)
printf("fail\n");
else
printf ("pass\n"):
return 1;
}
THE OUTPUT IS AS FOLLOWS:
pass
pointer fail
How is this possible, when arg != NULL but still the pointer is NULL. As i expected any assignment at arg would be reflected in pointer also.
Can anybody let me what could have gone wrong. I'm unable to share the entire code snippets as the code is huge..
In your first block of code you are saying you if assign null to pointer not if pointer equals null.
if (pointer = NULL)
This is your problem. If your compiler isn't warning you about this, either turn your warnings up, or find a better compiler. What you want is what you have in your second if block:
if (pointer == NULL)
The reason it isn't working with the one = is because you are assigning NULL to pointer within the if statement. The result of that expression is NULL, hence the if block doesn't execute, but the else block does.
Alternatively, some people find it easier to read by omitting the comparison to NULL altogether:
if (pointer)
{
// pointer is not NULL
}
else
{
// pointer is NULL
}
Use this way (Make following changes at respective places)
...
res = hashget(key, &pointer);
if (pointer == NULL)
printf ("pointer fail\n");
else
printf ("pointer pass\n");
...
...
int hashget(int key, USSD_STRUCT *arg)
...
...
*arg = data;
if (*arg == NULL)
printf("fail\n");
else
printf ("pass\n"):
return 1;
}
...
Reason:
In your program you are passing pointer as pass by value, In my method I am passing as pass by pointer or basically passing the address of pointer because its value needs to be modified in calling function.
EDIT: (After your modification in the question)
USSD init = (USSD)malloc(sizeof(USSD));
This is wrong. init should be a pointer.
Use USSD *init = (USSD*)malloc(sizeof(USSD));.
And after you allocated memory to init->msisdn, init->language, init->ussd_string, why are you setting them to NULL, that too just by referencing the inner variables of struct like this: msisdn = language = ussd_string = NULL.
And even if you correct all these mistakes, my answer is OK, since you cannot modify value of pointer by making a call like this: res = hashget(key, pointer);, using this you can only modify *pointer i.e. value pointed to by the pointer.

Seg Fault when copying a pointer

How come the following code result in seg fault? Basically after I copy the head pointer to temp, the head pointer gone.
typedef struct address * paddress; // defines struct pointer
void addAddressToList(paddress head, int addr[])
{
if (head == NULL) {
//head->addrArray = addr; // if list is initially empty
} else {
paddress temp;
temp = head;
while (temp->right != NULL) {
temp = temp->right; // go to end of the list
}
paddress newAddress = (paddress)malloc(sizeof(paddress*));
newAddress->intAddr = addr;
newAddress->right = NULL;
newAddress->left = temp; // connect the new address
temp->right = newAddress;
}
}
main() {
paddress addressListHead;
addressListHead = (paddress)malloc(sizeof(paddress*));
int intAddr1[] = {1,2,3,4,5,6,7};
char hexAddr1[] = "123456";
int intAddr2[] = {16,14,13,12,11};
char hexAddr2[] = "fedcb";
addressListHead->intAddr = intAddr1;
addressListHead->hexAddr = hexAddr1;
addAddressToList(addressListHead, intAddr2);
}
paddress addressListHead;
addressListHead = (paddress)malloc(sizeof(paddress*));
It seems to get rid of the compilation error, you have type casted what malloc is returning to paddress. addressListHead is a pointer, which means it can hold the address of an object but not the address of a pointer. The malloc here statement doesn't create an object. You need to change this -
addressListHead = (paddress)malloc(sizeof(paddress*));
to
addressListHead = (paddress)malloc(sizeof(struct address));
in main and addAddressToList functions.
Segmentation fault :
else {
paddress temp;
temp = head;
while (temp->right != NULL) {
temp = temp->right; // go to end of the list
}
I understand paddress::right is a pointer with the fact you are comparing it to NULL. But what is temp::right is initialized to. It is pointing to some garbage address and so you cannot ask for it to compare with NULL. Make it point to a valid memory location.
There is more than one problem in your code.
Firstly, the usual advice: stop using sizeof with type names (as much as possible). Use sizeof with expressions, not types. Type names belong in declarations and nowhere else.
Your problem with memory allocation could have been prevented if you used this malloc idiom
T *p = malloc(n * sizeof *p);
i.e. sizeof should be applied to *p, where p is the pointer to the array you are allocating and n is the total number of elements in that array. That way you never have to guess what type name you should specify under sizeof (an that way your code becomes type-independent).
In your case you are allocating just one object, so the code should look as
paddress newAddress = malloc(sizeof *newAddress);
(And don't cast the result of malloc - there's absolutely no point in doing that).
Secondly, when you the head element of the list, you need to initialize all the fields. Yet you never initialize right (or left) in the head element. Hence the crash even when the correct amount of memory is allocated.
In main(), you want
addressListHead = (paddress)malloc(sizeof(address));
That makes sure you get enough bytes to hold an address.
First error:
addressListHead = (paddress)malloc(sizeof(paddress*));
paddress* means a pointer to paddress which itself is a pointer to struct address. Hence paddress* is a pointer to a pointer to struct address. You would want to do:
addressListHead = (paddress)malloc(sizeof(struct address));
Also, I see that you made a similar mistake yesterday. Why do I get a seg fault? I want to put a char array pointer inside a struct
It's important to understand the concept of pointers properly. I would definitely recommend you to go through some tutorials on pointers. If you need help with that, let me know.

Resources