How to realloc a memory? I keep getting segmentation fault - c

I keep geeting a segfault in the main function. I create a pointer to a struct I created and I pass it's reference to another function which allocates and reallocates memory. Then accessing it in the main function (where it was originally defined) causes a segfault.
Here is my test code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct {
char desc[20];
int nr;
} Kap;
void read(Kap *k);
int main(void) {
Kap *k = NULL;
read(k);
printf("__%s %d\n", k[4].desc, k[4].nr);
return 0;
}
void read(Kap *k) {
int size = 3;
k = (Kap*) calloc(size, sizeof(Kap));
k[0].nr = 1;
k[1].nr = 2;
k[2].nr = 3;
strcpy(k[0].desc, "hello0");
strcpy(k[1].desc, "hello1");
strcpy(k[2].desc, "hello2");
size *= 2;
k = (Kap*) realloc(k, sizeof(Kap)*size);
if(k == NULL) {
printf("ERROR\n");
exit(EXIT_FAILURE);
}
k[3].nr = 4;
k[4].nr = 5;
k[5].nr = 6;
strcpy(k[3].desc, "hello3");
strcpy(k[4].desc, "hello4");
strcpy(k[5].desc, "hello5");
}
What am I doing wrong?

Here's a simplified version of the problem you are having:
#include <stdio.h>
void func(int x)
{
x = 10;
}
int main()
{
int x = 5;
printf("x = %d\n", x);
func(x);
printf("x = %d\n", x);
}
The same reason x does not change is the reason that k does not change in your program. A simple way to fix it is this:
Kap *read()
{
Kap *k = calloc(...);
...
k = realloc(k, ...);
...
return k;
}
int main()
{
Kap *k = read();
...
}

The problem is you're not passing the pointer back to main(). Try something like this instead:
Kap * read();
int main(void) {
Kap *k = read();
printf("__%s %d\n", k[4].desc, k[4].nr);
return 0;
}
Kap * read() {
... everything else you're already doing ...
return k;
}
The code you showed passes a pointer by value into read(). The subroutine can use that pointer (though it's kind of useless since its local copy is immediately changed), however changes made within read() do not bubble back to its caller.
My suggestion is one method of allowing read() to send the new pointer back up, and it's probably the right method to choose. Another method is to change read()s signature to be void read(Kap **);, where it will receive a pointer to a pointer -- allowing it to modify the caller's pointer (due to being passed by reference).

Related

initialize struct from function call

Feel like im taking crazy pills just trying to do literally the simplest stuff I can imagine in C. Any help would be extremely appreciated. why does this work?
#include <stdio.h>
#include <stdlib.h>
#define Q_LIMT 100
typedef struct servers
{
int id;
int num_in_Q;
int server_status;
}SERVER;
void initialize(SERVER *s);
void initialize(SERVER *s)
{
int i=0,j=0;
for(i=0; i<2; i++) { //i=0; i=1
s[i].id = i; // 0, 1
s[i].num_in_Q = i*i + 1; // 1, 2
s[i].server_status = i+i + 2; // 2, 4
} // the bracket was missing
}
int main()
{
int i;
SERVER serv[2];
initialize(serv);
for(i=0; i<2; i++) {
printf("server[%d].id = %d\n", i, serv[i].id);
printf("server[%d].num_in_Q = %d\n", i, serv[i].num_in_Q);
but this throws away the initialized struct?
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
'''
int POINTERS_PER_INODE = 5;
struct Inode {
int valid;/* 0 == invalid, 1 == valid*/
int size;
int Blocks [5];
};
int InodeToString(char * InodeString, struct Inode iNode){
char * blockBuffer;
sprintf(InodeString, "%d", iNode.valid);
int i;
for (i = 0; i < POINTERS_PER_INODE; i++){
blockBuffer = malloc(8);
sprintf(blockBuffer, "%d", iNode.Blocks[i]); //no valid pointers yet
strcat(InodeString,blockBuffer);
free(blockBuffer);
}
return 0;
}
int initializeInode(struct Inode iNode){
int i;
for (i = 0; i < POINTERS_PER_INODE; i++){
iNode.Blocks[i] = -1; //no valid pointers yet
}
iNode.valid = 0; //initialized as invalid inode
return 0;
}
int main() {
struct Inode iNode1;
initializeInode(iNode1);
char * InodeString;
InodeString = malloc(20);
InodeToString(InodeString, iNode1);
printf("%s", InodeString);
free(InodeString);
iNode1.valid = 1;
InodeString = malloc(20);
InodeToString(InodeString, iNode1);
printf("%s", InodeString);
return 0;
}
This is test code btw, so the includes probably dont make sense. stack overflow says I dont have enough details so I guess I have to keep typing sentences. Let me know if theres any details that would make this more clear. its for a basic super simplified file system simulation project. it seemed in a previous version when I initialized the inode outside of the function, I was able to pass the string into the string function, assign it values, not use it as the return value and still end up on the other side of the function with an updated string.
As is normal in C, arguments to a function are passed by value. The object called iNode in initializeInode is local to that function, and changes to it have no effect on any other object in the program. If you want a function to modify an object that's local to the caller, you have to pass a pointer to it, and dereference that pointer to get at the caller's object.
So what you probably want is:
int initializeInode(struct Inode *iNode){
int i;
for (i = 0; i < POINTERS_PER_INODE; i++){
iNode->Blocks[i] = -1; //no valid pointers yet
}
iNode->valid = 0; //initialized as invalid inode
return 0;
}
int main() {
struct Inode iNode1;
initializeInode(&iNode1);
// ...
}

C: Store reference to stack variable in array

I'm writing a program that's running on an embedded MCU, so all of my memory allocations are to the stack (no malloc()). I have a struct being created in a function and returned to a caller, and I'm trying to keep a reference to that variable in an array, prior to being returned.
The problem is that the variable stored in the array seems to be a copy of the variable returned to the caller, so they're not in sync. The code below illustrates the issue:
#include <stdio.h>
int *ARRAY_OF_VARIABLES[1];
int initalizeVariables() {
int i = 0;
ARRAY_OF_VARIABLES[0] = &i;
return i;
}
int main(void)
{
int test = initalizeVariables();
test = 1;
printf ("Test: %d, ARRAY_OF_VARIABLES[0]: %d\r\n", test, (int)*ARRAY_OF_VARIABLES[0]);
}
This prints: Test: 1, ARRAY_OF_VARIABLES[0]: 0
How can I keep "test" and "ARRAY_OF_VARIABLES[0]" in sync without malloc() and pointers?
I solved this by creating a function that I can pass a pointer of i back into for storage in ARRAY_OF_VARIABLES. Here's the new code:
#include <stdio.h>
int *ARRAY_OF_VARIABLES[1];
int initalizeVariables() {
int i = 0;
return i;
}
void setInArray(int *i, int idx) {
ARRAY_OF_VARIABLES[idx] = i;
}
int main(void)
{
int test = initalizeVariables();
setInArray(&test, 0);
test = 123;
printf ("Test: %d, ARRAY_OF_VARIABLES[0]: %d\r\n", test, *ARRAY_OF_VARIABLES[0]);
}
If there are any better ways to do this, please feel free to post them :).

Why does this C struct initialization code produce a bus error? [duplicate]

This question already has answers here:
How to change value of variable passed as argument?
(4 answers)
Closed 5 years ago.
When designing a game entity system in C, I attempted an "equals-free" initialization approach. I was surprised to see a linter tell me there was a memory leak at the end of my init function, and that my variable ent was never initialized in the following code. It turned out to be right because I got a "bus error":
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
} entity_t;
void entity_init(entity_t* ent, int _x, int _y)
{
ent = malloc(sizeof(*ent));
ent->x = _x;
ent->y = _y;
}
int main(void)
{
entity_t* ent;
entity_init(ent, 10, 24);
printf("Entity: x%d y%d", ent->x, ent->y);
return 0;
}
What I thought the above code would do, was take my empty ent pointer supplied as an argument, tell it to point to some newly allocated memory, and then fill in that memory and everything would be fine. I have no idea what it's really doing to cause a "bus error", am I missing something critical about pointers and malloc?
I vaguely remember seeing something very similar to this done before in some C code (equals-free struct initialization) and I would strongly prefer to use an equals-free initialization style similar to this (broken) code if such a thing is possible in C.
Move the malloc call outside the initialization function:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
} entity_t;
void entity_init(entity_t* ent, int _x, int _y)
{
ent->x = _x;
ent->y = _y;
}
int main(void)
{
entity_t* ent;
if(NULL==(ent = malloc(sizeof(*ent))))
return 1;
entity_init(ent, 10, 24);
printf("Entity: x%d y%d", ent->x, ent->y);
return 0;
}
You're assigning the pointer to the allocated block to a local variable (ent). That can't affect the ent in main.
If you wanted to keep the malloc in entity_init, you should use a double pointer, but you should also change the signature to allow for a way to signal malloc failure from entity_init
int entity_init(entity_t **ent, int _x, int _y)
{
if(NULL==(*ent = malloc(sizeof(**ent))))
return -1;
(*ent)->x = _x;
(*ent)->y = _y;
}
int main(void)
{
entity_t* ent;
if(0>entity_init(&ent, 10, 24))
return 1;
printf("Entity: x%d y%d", ent->x, ent->y);
return 0;
}
A more usual pattern for this would be:
entity_t *entity_new(int _x, int _y)
{
entity_t *ent = malloc(sizeof(*ent));
if (NULL==ent)
return NULL;
ent->x = _x;
ent->y = _y;
return ent;
}
int main(void)
{
entity_t* ent;
if(NULL==(ent=entity_new(10,24)))
return 1;
printf("Entity: x%d y%d", ent->x, ent->y);
return 0;
}
If you must allocate within the entity_init() function, you need to either return a pointer to the allocation, or add a layer of indirection by making ent a pointer to pointer to entity_t. In the posted code, within entity_init() ent is a copy of the pointer which was passed to the function. Any changes made to this pointer, such as assigning the address of a memory allocation to the pointer, will not be visible from the calling function since this copy will cease to exist after the function returns.
Also, note that you need to check the value returned from malloc() to be sure that the allocation was successful. If successful, the function can continue with the initialization process; if not, ent can remain a null pointer, which should be checked in the calling function:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
} entity_t;
void entity_init(entity_t **ent, int _x, int _y)
{
*ent = malloc(sizeof **ent);
if (*ent) {
(*ent)->x = _x;
(*ent)->y = _y;
}
}
int main(void)
{
entity_t *ent;
entity_init(&ent, 10, 24);
if (ent == NULL) {
fprintf(stderr, "Allocation failure in entity_init()\n");
exit(EXIT_FAILURE);
}
printf("Entity: x%d y%d\n", ent->x, ent->y);
return 0;
}
Program output:
Entity: x10 y24

is it possible? passing address of local static value to main pointer?

#include<stdio.h>
void f(int *p) {
static int data = 5;
p=&data;
}
int main(void) {
int *ip=NULL;
f(ip);
printf("%d\n", *ip);
return 0;
}
if it is possible.
what is cause error?
how can I fix the code?
In this way you end up changing the value of a local pointer, you need to pass a pointer to pointer (&) from main and use the dereference operator (*) in the function:
#include <stdio.h>
void f(int **p) {
static int data = 5;
*p = &data;
}
int main(void) {
int *ip = NULL;
f(&ip);
printf("%d\n", *ip);
return 0;
}
But usually we prefer to work with the same level of indirection returning the address from the function, this is easier to read (at least for me):
#include <stdio.h>
int *f(void) {
static int data = 5;
return &data;
}
int main(void) {
int *ip = f();
printf("%d\n", *ip);
return 0;
}
You have to pass a pointer to the pointer to change the value of the actual pointer:
void some_fun(int **p)
{
static int i = 10;
*p = &i;
}
That being said, it is not necessarily advisable to do that. The only direct use I could think of is to delay the execution of the initialization of a global until its first use.

Vector in C crashing

I tried to write a vector in c using memory operations.Compiler shows no errors but if I try to print an element from the vector it simply crashes. And whenever I try to print destination variable (printf((int) destination)) the program crashes again.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct{
void* elemList;
int elemSize;
int maxSize;
int curSize;
}myvector;
void initVec(myvector * vec, int typeSize){
vec->curSize = 0;
vec->maxSize = 10;
vec->elemSize =typeSize;
vec->elemList = malloc(10*sizeof(typeSize));
}
void add(myvector * vec, void* elem){
if(vec->curSize >= vec->maxSize){
vec->elemList = realloc(vec->elemList, vec->maxSize*2);
}
memcpy(&vec->elemList[vec->curSize],elem,vec->elemSize);
}
void get(myvector * vec, int index, void* destination){
if(index > vec->curSize || index < 0){
printf("Invalid Index");
return;
}
destination = malloc(vec->elemSize);
memcpy(destination,&vec->elemList[index], vec->elemSize);
}
int main()
{
myvector newVec;
initVec(&newVec,sizeof(int));
int a = 5;
add(&newVec,&a);
int* b;
get(&newVec,0,b);
printf(*b);//this is where the program crashes
return 0;
}
Basically the pointer in the get is not handled correctly. It's being passed by value so a copy of the pointer is made, the copy is modified (memory allocation is done for this copy), but the original pointer once you quit the get method is not pointing to a valid memory. You have to pass the address of the pointer. Following is a modified code (note the double ** in the destination in the get method). Basically I pass the address of the "destination" pointer instead of the pointer itself. Additionally I fixed the line sizeof(typeSize) .. it should be typeSize only since you are already calling the initVec method with sizeof operator.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct{
void* elemList;
int elemSize;
int maxSize;
int curSize;
}myvector;
void initVec(myvector * vec, int typeSize){
vec->curSize = 0;
vec->maxSize = 10;
vec->elemSize = typeSize;
vec->elemList = malloc(vec->maxSize*typeSize);
}
void add(myvector * vec, void* elem){
if(vec->curSize >= vec->maxSize)
{
vec->elemList = realloc(vec->elemList, vec->maxSize*2);
}
memcpy(&vec->elemList[vec->curSize], elem, vec->elemSize);
vec->curSize++;
}
void get(myvector * vec, int index, void** destination){
if(index > vec->curSize || index < 0)
{
printf("Invalid Index");
return;
}
*destination = malloc(vec->elemSize);
memcpy(*destination, &vec->elemList[index], vec->elemSize);
}
int main()
{
myvector newVec;
initVec(&newVec,sizeof(int));
int a = 5;
add(&newVec,&a);
int* b;
get(&newVec, 0, &b);
printf("value of b is %d\n", *b); // This works correctly now
return 0;
}
A couple of issues with the code :
vec->elemList = malloc(10*sizeof(typeSize)); should be vec->elemList = malloc(10*typeSize);
If you would like get to create a pointer to int I would recommend either defining it like int* get(myvector * vec, int index) and return a newly allocated pointer to int or in the main function use :
int b;
get(&newVec, 0, &b);
the latter will also avoid memory leaks.
printf(*b); is wrong as you are passing an int and it expects a char* use either printf("%d", b); if b is an int or printf("%d", b);if b is aint`
you are using malloc a lot but no free. In this particular program you don't get memory leaks as the OS will reclaim all memory when main returns. But think early about a function to clear your vector and.
*b shouldn't be a valid pointer to string, so it will cause crash.
Try printing it by printf("%d",*b);
To make it better, you should free the buffer that are allocated by malloc.
UPDATE
The get function is wrong since it throws away the buffer allocated to destination
get function and main function should be like this:
void get(myvector * vec, int index, void** destination){
if(index > vec->curSize || index < 0){
printf("Invalid Index");
return;
}
*destination = malloc(vec->elemSize);
memcpy(*destination,&vec->elemList[index], vec->elemSize);
}
int main()
{
myvector newVec;
initVec(&newVec,sizeof(int));
int a = 5;
add(&newVec,&a);
int* b;
get(&newVec,0,&b);
printf("%d",*b);//this is where the program crashes
return 0;
}
But this still gives me Segmentation Fault. I'm working on.
UPDATE 2
You should think about the size of each elements.
You also forget the size information in add function.
This code should work if we don't care about memory leak.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct{
void* elemList;
int elemSize;
int maxSize;
int curSize;
}myvector;
void initVec(myvector * vec, int typeSize){
vec->curSize = 0;
vec->maxSize = 10;
vec->elemSize =typeSize;
vec->elemList = malloc(vec->maxSize*vec->elemSize);
}
void add(myvector * vec, void* elem){
if(vec->curSize >= vec->maxSize){
vec->elemList = realloc(vec->elemList, vec->elemSize * vec->maxSize*2);
vec->maxSize *= 2;
}
memcpy(vec->elemList + vec->curSize * vec->elemSize,elem,vec->elemSize);
vec->curSize++;
}
void get(myvector * vec, int index, void** destination){
if(index >= vec->curSize || index < 0){
printf("Invalid Index");
return;
}
*destination = malloc(vec->elemSize);
memcpy(*destination,vec->elemList + index * vec->elemSize, vec->elemSize);
}
int main()
{
myvector newVec;
initVec(&newVec,sizeof(int));
int a = 5;
add(&newVec,&a);
int* b;
get(&newVec,0,(void**)&b);
printf("%d",*b);
return 0;
}

Resources