Segmentation fault when initialization array - c

I have a structure called string
typedef struct {
char *s;
int len;
} string_t;
typedef struct {
uint32_t numb;
} msg_t;
where in the function
void myfunct()
{
msg_t msg;
memset(&msg, 0, sizeof(msg));
msg.numb = 1;
char *ClientSendBuf[sizeof(msg)];
string_t buffer = {ClientSendBuf[sizeof(msg)],strlen(ClientSendBuf[sizeof(msg)])};
}
Tried to initialize an array (basically a buffer that I need to send later on) using UDP,
but it gives me an error of segmentation fault (on the third line in void myfunct.
So the thing with buffer is that it should be a type of string_t, how can I fix this segmentation fault?
P.S. I forgot to mention, I want to copy the whole structure to the buffer variable (that should be type string_t) using memcopy. So am I doing the wrong thing above? How can I do this?

There are a few things you have to consider in initializing your structure, as it has a pointer member char *s simple assignment will not work. Simple assignment will just copy the pointer address and not the content it is pointing to.
There are a few problems in your assignment code:
1. You declared an array of char * with sizeof(msg) elements, none of which are allocated memory; but your structure need char * and not char *[]
2. You are accessing an array element which is out of bounds (ClientSendBuf[sizeof(msg)]) and also not pointing to any valid address.
You can create a simple char array & copy it to the structure. As you are using a pointer member it is your responsibility to allocate memory and free memory.
Hope the code below can provide you with some references:
void myfunct()
{
msg_t msg;
memset(&msg, 0, sizeof(msg));
msg.numb = 1;
char ClientSendBuf[] = "This is my message";
string_t buffer = {
strdup(ClientSendBuf), /*Can return NULL so add error check*/
strlen(ClientSendBuf)
};
/** Or **/
string_t buffer;
buffer.s = malloc(strlen(ClientSendBuf)+1);
if(NULL == buffer.s)
{
/* Memory allocation failed. Handle error.*/
}
/* Zero fill */
memset(buffer.s, 0, strlen(ClientSendBuf)+1);
strcpy(buffer.s, ClientSendBuf);
buffer.len = strlen(ClientSendBuf);
/*Opeartions with buffer*/
/*Call free in both cases !*/
free(buffer.s);
}
Hope this help!

ClientSendBuf - put some thing in it and also put it on the heap.

The problem is that you don't allocate memory to any element of ClientSendBuf. You should use malloc here to first allocate the memory.

I see two things that are wrong. First, accessing ClientSendBuf[sizeof(msg)] is undefined behavior, because that character is after the end of CliendSendBuf. Then you're assigning a char (namely ClientSendBuf[sizeof(msg)]) when a char * is expected.
And if you want to use buffer outside that function you have to put ClientSendBuf on the heap, because it will be overwritten by other stack frames after you exit (i.e. sort of deleted), so the pointed data will be throwed off.
Now, since you want a copy of the whole ClientSendBuff, you need an array of string_t. Then, you assign every pointer in ClienSendBuff to buffer:
char *ClientSendBuff[sizeof(msg)];
string_t buffer[sizeof(msg)];
int i;
for(i = 0; i < sizeof(msg); i++) {
ClientSendBuff[i] = malloc(100); // you have to initialize (and free when
buffer[i].s = ClientSendBuff[i]; // you don't need them anymore) every pointer
buffer[i].len = 100;
}
But I'm not sure if I got your point. How can a char * [] fit in a char*?

Related

Assign characters to arrow pointer in c

struct room
{
char venue[15]; //variable
}
*stream;
.
.
.
void idealounge(){
int i,idealounge[10];
char room1[10]="MMLC";
*** ** stream->venue = room1;*****
}
This is a room booking system.
The name of the room called MMLC.
I expect it can store "MMLC" to stream->venue but it shows errors like "incompatible values" etc.
The statement:
char venue[15];
declares venue to be an array of size 15 of char. Then,
char room1[10]="MMLC";
initialises the first 4 bytes of room1 with the string literal "MMLC", setting the rest to \0.
Then,
stream->venue = room1;
is invalid, because venue is an array, not a pointer. Arrays are not modifiable l-values. You can't assign arrays like this.
If you want to copy the contents of room1 to the contents of venue, use standard strcpy().
That being said,
struct room
{
char venue[15]; //variable
}
*stream;
only allocates space for the pointer, which is uninitialized and isn't pointing to anything meaningful. So first allocate memory and initialise the pointer:¹
stream = malloc (sizeof (struct room));
Then check if it succeeded:²
if (!stream) {
perror ("malloc()");
/* handle error here...*/
}
Now perform the string copy.
Alternatively, you can allocate the struct with automatic storage duration, which is simpler and less error-prone:
struct room bedroom;
and then assign it's address to the pointer:
stream = &bedroom;
This avoids the need for dynamic memory allocation, which you might fail to free() later on.
[1] — NB that I do not cast the result of malloc(). malloc() returns a generic void *, or void pointer, which is automatically promoted to the correct type. So there's no need to cast, and doing so might hide a potential bug.
See also: Do I cast the result of malloc?
[2] — POSIX-compliant systems set errno on malloc() failure, the above code snippet assumes it does. But you may not wish to take it for granted, and handle the error in another way.
struct room
{
char venue[15]; //variable
}
*stream = NULL;
void idealounge() {
int i;
int idealounge[10];
char room1[10]="MMLC";
stream = (struct room *)malloc(sizeof(struct room));
strcpy(stream->venue, room1);
}
You should write this way.

C - Struct- Integer to a pointer without cast

So I'm having a bit of trouble figuring out what is going on when I malloc an array that is a member of the struct?
The following error message occurred :
"assignment makes integer from pointer without a cast".
It would be greatly appreciated if someone can help me see where I went wrong in the malloc.
typedef struct _big_num {
int nbytes; // size of array
Byte *bytes; /// array of Bytes
} BigNum;
void initBigNum(BigNum *n, int Nbytes)
{
int i;
n->nbytes = Nbytes;
for (i = 0; i < Nbytes; i++) {
n->bytes[i] = malloc(sizeof(Byte)); //This is where the error came up
n->bytes[i] = 0;
assert(n->bytes[i] == 0);
}
return;
}
n->bytes[i] is of type Byte, it's a single element in the "array". The malloc call returns a pointer.
You don't allocate the array itself, but instead try to allocate each element separately, which isn't how it works. Besides the compiler message, n->bytes may not point to a valid location, making the dereference n->bytes[i] invalid for any index.
You probably want
void initBifNum(BigNum *n, int NBytes)
{
// Initialize members and allocate memory for array
n->nbytes = NBytes;
n->bytes = malloc(sizeof *n->bytes * NBytes);
// Initialize all elements in the array to zero
memset(n->bytes, 0, sizeof *n->nbytes * NBytes);
}
n->bytes[i] is really *n->(bytes+i). So you're assigning the memory address returned by malloc to type Byte instead of to a pointer.
It's worth pointing out that in the very next line, you assign 0 to n->bytes[i], even though you just attempted to assign it an address. If you're trying to allocate memory that's set to 0, just use calloc - it allocates memory and sets it to 0 for you.

How to properly malloc for array of struct in C

I will read in two set of char* (or strings) using strtok, and since those two set of chars are related, (address : command\n) I decided to use a structure.
struct line* array = (struct line*)malloc(sizeof(file) * sizeof(struct line*));
This line mallocing space for the function gives me a segmentation fault and was wondering if you can tell me a proper way to malloc space for it. For context, here is the rest of my code:
struct line
{
char* addr;
char* inst;
};
while loop{
x = strtok(line,": ");
y = strtok(NULL,"\n");
strcpy(array[i].addr,x); //assume that x and y are always 3characters
strcpy(array[i].inst,++y);
i++;
}
Allocating works the same for all types. If you need to allocate an array of line structs, you do that with:
struct line* array = malloc(number_of_elements * sizeof(struct line));
In your code, you were allocating an array that had the appropriate size for line pointers, not for line structs. Also note that there is no reason to cast the return value of malloc().
Note that's it's better style to use:
sizeof(*array)
instead of:
sizeof(struct line)
The reason for this is that the allocation will still work as intended in case you change the type of array. In this case this is unlikely, but it's just a general thing worth getting used to.
Also note that it's possible to avoid having to repeat the word struct over and over again, by typedefing the struct:
typedef struct line
{
char* addr;
char* inst;
} line;
You can then just do:
line* array = malloc(number_of_elements * sizeof(*array));
Of course don't forget to also allocate memory for array.addr and array.inst.
For what you have described, You do not need to allocate memory for your struct, rather, you need to allocate memory for the members char *addr;, and char *inst;. If you want to have a single copy of that structure, the first section of code illustrates how to initialize, and assign values. If you want an array, the second code example illustrates the differences.
This illustrates how to allocate memory for the members of a single struct line:
typedef struct
{
char* addr;
char* inst;
}LINE;
LINE line;
int main(void)
{
strcpy(line.addr, "anystring"); //will fail
line.addr = malloc(80);
line.inst = malloc(80);
strcpy(line.addr, "someString");//success;
strcpy(line.inst, "someOtherString");//success;
}
For array of struct line...
typedef struct
{
char* addr;
char* inst;
}LINE; //same struct definition
LINE line[10]; //but create an array of line here.
int main(void)
{
int i;
for(i=0;i<10;i++)
{
line[i].addr = malloc(80);
line[i].inst = malloc(80);
}
for(i=0;i<10;i++)
{
strcpy(line[i].addr, "someString");
strcpy(line[i].inst, "someOtherString");
}
//when done, free memory
for(i=0;i<10;i++)
{
free(line[i].addr);
free(line[i].inst);
}
}
Added to address comment
Addressing the comment under this answer from #Adam Liss, the following code illustrates the following improvements using strdup(): 1) Uses only memory needed. 2) Performs memory creation and copy operations in one step, so the the following blocks:
for(i=0;i<10;i++)
{
line[i].addr = malloc(80);
line[i].inst = malloc(80);
}
for(i=0;i<10;i++)
{
strcpy(line[i].addr, "someString");
strcpy(line[i].inst, "someOtherString");
}
Become:
for(i=0;i<10;i++)
{
line[i].addr = strdup("someString");
line[i].inst = strdup("someOtherString");
}
One more note: Error handling was not included in examples above to avoid muddling up focus on the main concepts: But for the sake of completeness, because both malloc() and strdup() can fail, actual usage for each of these two functions, should include a test before using, eg:
Rather than
line[i].addr = strdup("someString");
line[i].inst = strdup("someOtherString");
The code should include
line[i].addr = strdup("someString");
if(!line[i].addr)
{
//error handling code here
}
line[i].inst = strdup("someOtherString");
if(!line[i].inst)
{
//error handling code here
}

Changing values in elements of an array of structs

I am working on an assignment and ran into challenging problem. As far as I'm concerned and from what I've learnt the code that follows should be correct however it does not work. Basically what I am trying to is copy a string value into the variable member of a structure the is part of an array passed into a method as a pointer. What am I missing?
typedef struct
{
char * name; //variable in struct I am trying to access
} Struct;
void foo(Struct * arr) //array of Structs passed into function as a pointer
{
int i = 0;
while(i++ < 2)
{
arr[i].name = malloc(sizeof(char *)); //assigning memory to variable in each Struct
arr[i].name = strdup("name"); //copying "name" to variable in each Struct
printf("C - %s\n", arr[i].name); //printing out name variable in each Struct
}
}
main()
{
Struct * arr; //defining pointer
arr = calloc(2, sizeof(Struct)); //allocating memory so pointer can hold 2 Structs
foo(arr); //calling function foo passing pointer into function
return 0;
}
This code compiles and runs however it does not do what it is designed to do. Forgive me if it is something trivial. I am new to the language C
Two issues:
while(i++ < 2) This line changes the value of i as soon as it checks it, so your loop body will not be the same as it was checked.
arr[i].name = strdup("name"); overwrites the value of the .name pointer, causing a memory leak of the memory you malloc()'ed earlier.
Extending on 2 pointed out correctly already,
arr[i].name = strdup("name");
Even if you use following instead of above,
strcpy(array[i].name, "name");
you haven't allocated enough bytes to store the string i.e. this is wrong
arr[i].name = malloc(sizeof(char *));
// even if pointer is 8 byte here, concept isn't right
Should be something like
arr[i].name = malloc(strlen("name")+1);
// or MAX_SIZE where it is greater than the possible "name".
Or better yet, remove the malloc at all, strdup takes care of allocation itself
This is not answering your question directly, but addresses an issue to big to put into a comment...
Additional issue: You probably did not intend to allocate only a (char *) worth of memory to a variable intended to hold at least "name". Change;
arr[i].name = malloc(sizeof(char *));
to:
arr[i].name = malloc(sizeof(char)*strlen("name")+1); //+1 for '\0'
or better yet, use char *name="name";, then:
arr[i].name = malloc(sizeof(char)*strlen(name)+1);
Even more general (and better):
char *name;
name = malloc(strlen(someInputString)+1);
//do stuff with name...
free(name);
Now, you can allocate name to any length needed based on the length of someInputString.
[EDIT]
Etienz, I wanted to address one more thing, alluded to by #H2CO3 above, but not really explained, that I think might be useful to you:
Regarding your desire to have room for two structs, because you typedef'd your struct, you can simply do something like this: (but I am going to change the name you used from Struct to NAME :) The whole point being that when a struct is created as an array, you do not need to use calloc or malloc to create space for them, it is done as shown below...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char *name;
}NAME;
//use new variable type NAME to create global variables:
NAME n[2], *pN; //2 copies AND pointer created here
//prototype func
int func(NAME *a);
int main()
{
pN = &n[0]; //pointer initialized here
func(pN); //pointer used here (no malloc or calloc)
printf("name1 is %s\nname 2 is %s", pN[0].name, pN[1].name);
return 0;
}
int func(NAME *a)
{
char namme1[]="andrew";
char namme2[]="billebong";
//You DO have to allocate the members though
a[0].name = malloc(strlen(namme1)+1);
a[1].name = malloc(strlen(namme2)+1);
strcpy(a[0].name, namme1);
strcpy(a[1].name, namme2);
return 0;
}

c malloc in other function and structs

Im having problems with c and pointers. I keep grinding on this and it has to be easy. I have a struct and I allocate in one function, then pass the pointer back to the original function. But when I try to fill the values of the struct with other variables, and then print them or copy them , the app segfaults saying the memory address is out of bounds.
struct memcache_buffer{
int elements, action;
char keys[MAX_KEYS], values[MAX_KEYS], returns[MAX_KEYS]; //action 0 = delete , 1 = get 2 = set
}memcache_buffer;
struct memcache_buffer* memcache_allocate_buffer(int size){
struct memcache_buffer *buffer;
buffer =malloc(sizeof(struct memcache_buffer));
return buffer;
}
void memcache_set(char * key, char * value){
pthread_t process_t;
struct memcache_buffer *buffer=memcache_allocate_buffer(1);
char keys,values;
buffer->elements = 1;
buffer->action=2;
//printf("crash?\n");
printf("%s %s",key,value);
snprintf(buffer->keys[0],KEY_SIZE,"%s",key);
snprintf(buffer->values[0],VALUE_SIZE,"%s",value);
pthread_create(&process_t,NULL,memcache_process,buffer);
}
am I allocating the memory right? allocating memory and these pointers are sure rough, especially only messing with php in the past.
Here's your problem:
struct memcache_buffer{
char keys[MAX_KEYS], values[MAX_KEYS]
}
snprintf(buffer->keys[0],KEY_SIZE,"%s",key);
^^^
snprintf(buffer->values[0],VALUE_SIZE,"%s",value);
^^^
Drop the [0] or snprintf will try to dereference some bogus value.

Resources