c struct pointer array vs struct pointer pointer malloc - c

works:
struct data{
int val;
};
int main(void){
struct data *var[2];
(*var)->val = 6;
printf("%d\n", (*var)->val);
return 0;
}
segfault:
struct data{
int val;
};
int main(void){
struct data **var = malloc(3 * sizeof(struct data));
(*var)->val = 6; // <- crash
printf("%d\n", (*var)->val);
return 0;
}
can someone explain why segfault appears and give me an working example with minimal changes to the segfault code that i can understand pls.

The pointer is not malloc'ed, you are dereferencing an invalid pointer because your array is an array of poitners, and it's elements are not pointing to valid memory.
Try this
#include <stdio.h>
#include <stdlib.h>
struct data
{
int val;
};
int main(void)
{
struct data *var[2];
/* You need to malloc before dereferencing `var[0]` */
var[0] = malloc(sizeof(var[0][0]));
if (var[0] != NULL)
{
var[0]->val = 6;
printf("%d\n", var[0]->val);
free(var[0]);
}
return 0;
}
also, using (*var)->val = 6 is absolutely unnecessary and confusing.
In the second case, you should also do almost the same thing, except that the array of pointers is a pointer to an array of poitners and hence needs malloc() too, so your second example accidentally works because there is enough memory malloc()ed but it's also wrong, you should do it this way
#include <stdio.h>
#include <stdlib.h>
struct data
{
int val;
};
int main(void)
{
struct data **var;
var = malloc(2 * sizeof(var[0]));
if (var == NULL)
return -1;
/* You need to malloc before dereferencing `var[0]` */
var[0] = malloc(sizeof(var[0][0]));
if (var[0] != NULL)
{
var[0]->val = 6;
printf("%d\n", var[0]->val);
free(var[0]);
}
free(var);
return 0;
}

Related

Simply creating a data structure, how can it segfault?

i have a simple program on data structure but it segfaults and it frustrates me so much because i have absolutely no idea why. can anybody point out anything about this code (even not relevent)? thanks
#include <unistd.h>
#include <stdlib.h>
typedef struct prof
{
struct prof *next;
char c;
int x;
int y;
} profile;
profile *create_profile(char c, int i, int j)
{
profile *new_elem;
new_elem = (profile*)malloc(sizeof(profile));
if (new_elem == NULL)
return (NULL);
new_elem->next = NULL;
new_elem->c = c;
new_elem->x = i;
new_elem->y = j;
return (new_elem);
}
int main()
{
profile **king = NULL;
*king = create_profile('K', 1, 1);
return 0;
}
Your king is a pointer to a pointer to struct.
You need some place to store the pointer to struct in, but that is what you do not allocate.
You can introduce a pointer in order fix this.
int main()
{
/* introduce and NULL-init a pointer to struct */
profile* prince = NULL;
/* actually the init to NULL is not necessary,
because prince gets initialised later indirectly via king
(credits to alk), but it does not hurt and initialising everything
is a good habit. */
/* Introduce a pointer to pointer to struct,
initialised with the address of above pointer to struct,
the address of the above variable "prince" to be precise and clear.
The space for that automatic local variable is not dynamic,
it does not require a malloc. */
profile **king = &prince;
/* what the king is pointing to, i.e. the prince,
gets assigned what the function returns,
which is a cleanly allocated pointer to a new struct. */
*king = create_profile('K', 1, 1);
/* if king were still NULL, above statement would try to write
(the cleanly allocated pointer) into memory by dereferencing NULL ...
segfault!
(Well not necessarily, as alk points out, credits.
But dereferencing NULL is undefibed behaviour,
an almost guaranteed way to trouble in the long run
and in case a seggault is observed, a likely explanation.
*/
return 0;
}
This
profile **king = NULL;
*king = ...
dereferences NULL, which by itself already invokes undefined behaviour. On top of this the code then tries to write there. Not good, as NULL does not point to valid memory.
You have to allocate memory first to profile **king and then allocate memory to *king.
#include <unistd.h>
#include <stdlib.h>
typedef struct prof
{
struct prof *next;
char c;
int x;
int y;
} profile;
profile *create_profile(char c, int i, int j)
{
profile *new_elem;
new_elem = (profile*)malloc(sizeof(profile));
if (new_elem == NULL)
return (NULL);
new_elem->next = NULL;
new_elem->c = c;
new_elem->x = i;
new_elem->y = j;
return (new_elem);
}
int main()
{
profile **king = (profile**) malloc(sizeof(profile*)); // <-- see here
*king = create_profile('K', 1, 1);
return 0;
}
The code segfaults at
*king = create_profile('K', 1, 1);
Because you've defined king to
profile **king = NULL;
Meaning that king is now a pointer to a pointer. But king doesn't actually point anywhere, you say that it points to NULL. Dereferencing a pointer pointing to NULL will cause a segfault.
If you instead define king as
profile * king = NULL;
And assign it like
king = create_profile('K', 1, 1);
The code should no longer segfault.
You are confused in using double pointer. Try using like this
#include <unistd.h>
#include <stdlib.h>
typedef struct prof
{
struct prof *next;
char c;
int x;
int y;
} profile;
profile *create_profile(profile *head,char c, int i, int j)
{
profile *new_elem;
new_elem = (profile*)malloc(sizeof(profile));
if (new_elem == NULL)
return (NULL);
new_elem->next = head;
new_elem->c = c;
new_elem->x = i;
new_elem->y = j;
return (new_elem);
}
int main()
{
profile *king = NULL;
king = create_profile(king,'K', 1, 1);
return 0;
}

reallocating struct causes heap corruption

I'm writing a program in C that creates and tries to allocate the struct array. It manages to allocate the first block of memory and i successfully wrote the values on it but when i try to allocate a second time i get a error related to corrupted heap and "Invalid address specified to RtlValidateHeap".
here is my code (sorry for some parts in portuguese):
structs.h:
typedef struct vendedor
{
unsigned int numero;
char * nome;
float salario;
uint8_t comissao;
} VENDEDOR;
functions.h
extern vendedor * vende = (vendedor *)malloc(0);
extern unsigned int vende_sz = 0;
char * receberString()
{
int size = 0;
char temporary;
char * string = NULL;
string = (char *)malloc(size);
while (true)
{
scanf("%c", &temporary);
string = (char *)realloc(string, (size + 1) * sizeof(char));
if (temporary == '\n')
{
string[size] = '\0';
return string;
}
else
string[size] = temporary;
size++;
}
}
vendedor * alocarVende()
{
vendedor * tmpVende = (vendedor *)
realloc(vende, sizeof(vendedor)* vende_sz+1); //crashes here at second time
if (tmpVende == NULL)
{
printf("\nfailed to allocate.\n");
//free(tmpVende);
exit(-1);
}
else
{
vende = tmpVende;
//commented due to problems related
//free(tmpVende);
vende_sz++;
return vende;
}
}
main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include "structs.h"
#include "functions.h"
int main() {
login();
return 0;
}
bool login()
{
if (vende_sz == 0)
{
vende = alocarVende();
vende[0].salario = 666.66;
vende[0].numero = 1;
vende[0].comissao = 22;
vende[0].nome = receberString(); //dynamically allocates memory for a string using realloc
printf("%s", vende[0].nome);
vende = alocarVende();
vende[1].nome = receberString(); //dynamically allocates memory for a string using realloc
printf("%s", vende[1].nome);
return true;
}
}
any tips or help? I tried commenting free and some other things but still the same problem, thanks.
Edit: added more bits of code.
vende = tmpVende;
free(tmpVende);
This is precisely the same as:
vende = tmpVende;
free(vende);
Since vede and tmpVende are pointers with the same value, passing either one to free does the same thing -- frees the underlying thing they both point to.
vende[1].nome = receberString();
Thus this is a use after free that corrupts memory.
Also, you have this:
sizeof(vendedor)* vende_sz+1
Which doesn't do what you want because multiplication has higher precedence than addition.

Inserting and Manipulating Dynamic Array of Struct Pointers

Here is what I am trying to do:
1. Create an array of struct pointers.
2. Fill the array with malloc'd structs.
3. Then replace one element in the array with a new malloc'd struct
4. Have no memory leaks.
I have written a test program below, but I am getting seg faults due to invalid reads and writes on my call to memcpy. What am I doing wrong?
#include <stdlib.h>
#include <string.h>
struct my_struct {
int a;
int b;
};
int main(int argc, char *argv[])
{
struct my_struct **my_arr;
my_arr = (struct my_struct **) malloc(10 * sizeof(struct my_struct *));
int i;
for (i = 0; i < 10; i++) {
struct my_struct *my_str = (struct my_struct *) malloc(sizeof(struct my_struct *));
my_arr[i] = my_str;
}
free(my_arr[0]);
memcpy(my_arr[0], my_arr[1], sizeof(struct my_struct *) * 9);
my_arr[9] = (struct my_struct *) malloc(sizeof(struct my_struct *));
for (i = 0; i < 10; ++i) {
free(my_arr[i]);
}
free(my_arr);
}
free(my_arr[0]);
memcpy(my_arr[0], my_arr[1], sizeof(struct my_struct *) * 9);
This is problem , you first free(my_arr[0]) and then copy my_arr[1] at address it points to .
You are not supposed to access memory after freeing it .
And also specified in manpage
[...]The memory areas must not overlap. Use memmove if the
memory areas do overlap.
again you do this -
my_arr[9] = (struct my_struct *) malloc(sizeof(struct my_struct *));
thus , loosing reference to previous memory block it was pointing to .
This code works and I cleaned it up a bit:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct my_struct {
int a;
int b;
};
int main(){
const int structsz=sizeof(struct my_struct);
struct my_struct **my_arr=malloc(10 * structsz);
int i;
printf("Before\n");
for (i = 0; i < 10; i++){
my_arr[i]=malloc(structsz);
my_arr[i]->a=20+i;
my_arr[i]->b=10+i;
printf("i=%d a=%d, b=%d\n",i,my_arr[i]->a,my_arr[i]->b);
}
free(my_arr[9]);
my_arr[9]=malloc(structsz);
memcpy(my_arr[9], my_arr[1], structsz); //make 1st struct in array equal the 9th
free(my_arr[8]);
my_arr[8]=malloc(structsz);
memcpy(my_arr[8], my_arr[2], structsz); //make 2st struct in array equal the 8th
printf("After\n");
for (i = 0; i < 10; ++i) {
printf("i=%d a=%d, b=%d\n",i,my_arr[i]->a,my_arr[i]->b);
free(my_arr[i]);
}
free(my_arr);
return 0;
}
The reason why the third parameter of memcpy must be the same as the size of the structure is because both pointers in memcpy are the type of struct.
If the 3rd parameter is too large, then you can run into segmentation faults because you could try to copy memory that you're not allowed to access, or at best, you could be modifying other structs in your program.
If the 3rd parameter is too small, then you could receive invalid or insufficient data.

error of dereferencing pointer, in struct

I tried all the solutions on the site and didn't manage to fix this problem
i got a declared struct in my header
struct _fileNew;
typedef struct _fileNew fileNew;
in my source file I defined fileNew
struct _fileNew
{
char chars[];
};
now in my main i tried printing something inside the struct
fileNew* blu;
int i;
for ( i = 0; i < 10; i++)
{
blu->chars[i] = 'b';
}
printf("%s", blu->chars);
and i got
error: dereferencing pointer to incomplete type
I ran a debug and i saw that the cahrs was filled correctly but it won't print it. and I doin something wrong in the source file while defining the fileNew.?
thanks!
You need to allocate a memory block for the structure in heap and assign its address to Your pointer.
In C every string ends with a '\0' (string terminator), so You need to add it also.
#include <stdio.h>
#include <stdlib.h>
#define MAX_FILE_SIZE 128
struct _fileNew;
typedef struct _fileNew fileNew;
struct _fileNew
{
char chars[MAX_FILE_SIZE];
};
int main()
{
fileNew *blu = malloc(sizeof *blu);
int i;
for (i = 0; i < 10; i++)
{
blu->chars[i] = 'b';
}
blu->chars[i] = '\0';
printf("%s", blu->chars);
return 0;
}
You only have a pointer that is not actually pointing to anything and need to allocate size for the char[]. In main you need to assign the pointer to point at the declared struct OR use malloc as the other answers suggest:
static fileNew blu;
fileNew *p_blu = &blu;
...
p_blu->chars[i] = 'b';

Initializing values at the end of a pointer to pointer to pointer chain

Alright I've been cranking away at this all day (not hw), and though it may not be a particularly useful bit of code, it is a neat conceptual thing. I am trying to figure out the best way to set a value at the end of, for lack of a better name, a pointer to pointer to pointer chain. For example, I declare:
int *****ptr;
What is the best way to set each pointer to pointer segment, all the way down to the actual int value?
This code doesn't compile because it doesn't like the way I use and dereference void pointers:
#include <stdio.h>
#include <stdlib.h>
#define NUMPOINTERS 5
int main(int argc, char **argv)
{
int *****number;
*****number = malloc(sizeof(void*));
void *ptr = *number;
int i;
for(i = 1; i < NUMPOINTERS; i++)
{
if(i == NUMPOINTERS - 1)
{
ptr = malloc(sizeof(int));
int *iPtr = (int*)ptr;
*iPtr = 900;
break;
}
*ptr = malloc(sizeof(void*));
ptr = **ptr;
}
printf("%d", *****number);
return 0;
}
Is there some article out there that talks about ridiculous numbers of pointers to pointers and how to work with them?
What you have is pretty close. You probably want to work from the inside out, though. Here's a complete example based on your program (comments inline):
#include <stdio.h>
#include <stdlib.h>
#define NUMPOINTERS 5
int main(void)
{
void *ptr = malloc(sizeof(int)); // allocate space for the integer value
*(int *)ptr = 900; // initialize it
// iterate to create the nested pointers
for (int i = 1; i < NUMPOINTERS; i++)
{
void **newptr = malloc(sizeof(void *)); // create a new pointer
*newptr = ptr; // point it at what we have so far
ptr = newptr; // "step out" one level
}
int *****number = ptr; // make our 'int *****' pointer
printf("%d\n", *****number); // dereference and print the pointed-to value
return 0;
}

Resources