Unfathomable C structures - c

Hello I am experiencing something I really don't understand the principle with structures in C.
One of my structures contains 2 character strings (named 'seq' and 'foldedSeq'). Both these strings (should) have the same dimensions.
However when I try to modify one, the second automatically takes the same modifications at the same specified place of the string.
Here is the interesting chunk of code:
typedef struct MD {
int nb_line;
int nb_colomn;
EM ** matrix;
char * seq; // Initial sequence.
char * foldedSeq;
} MD;
void set_sequences(MD * M, char * seq) {
M->seq = seq;
M->foldedSeq = M->seq; //Purpose: give to foldedSeq the seq dimensions (perhaps it is useless).
printf("seq= %s\tstrlen= %d\nM->seq= %s\nM->foldedSeq= %s\n", seq, strlen(seq), M->seq, M->foldedSeq);
// Up to this point 'seq' = 'foldedSeq'
int i;
for( i = 0; i < strlen(seq); i++) {
M->foldedSeq[i] = '-'; // Original purpose: make 'foldedSeq' string filled with hyphens only.
}
printf("seq= %s\tstrlen= %d\nM->seq= %s\nM->foldedSeq= %s\n", seq, strlen(seq), M->seq, M->foldedSeq);
// Here is the problem: the string 'seq' REALLY IS modified alongside with 'foldedSeq'... WHY? :(
}
Since I wrote "M->foldedSeq[i]" should be modified, why would "M->seq[i]" be modified as well ??
Thank you for reading and providing me explanations, my logic found a dead end here.

M->seq = seq;
M->foldedSeq = M->seq;
is the same as saying
M->seq = seq;
M->foldedSeq = seq;
They are both pointing to the same location in memory. So modifying one is modifying both.
Probably what you want to do instead is malloc a block of memory that is the same length as the other.
M->foldedSeq = calloc(strlen(seq) + 1, sizeof(char));

What you're witnessing is simple pointer aliasing, a basic feature of the C language. Because you explicitly assign both seq and foldedSeq members to point to the same bit of memory, and modifications through one pointer will be witnessed by the other. If that's not what you intended/wanted, you'd need to copy the memory block of seq before assigning it to foldedSeq to keep the two distinct.

Because they both point to the same memory address and when you modify one you are modifying the other.
This assignment: M->foldedSeq = M->seq; is just assigning memory locations, not doing any sort of copy.
If you want to keep them separate, you will have to allocate memory and copy the string into the new memory.

Try either:
M->foldedSeq = strdp(M->seq) if you want to copy the content too.
Or:
M->foldedSeq = malloc(strlen(M->seq) + 1); to just have a new memory space of the same size.

This line:
M->foldedSeq = M->seq;
is setting the foldedSeq pointer to the same value as seq. It is not creating new space and copying the contents of seq to foldedSeq which is maybe where the confusion is. So when you modify either one the other will be modified as well. One possible solution is to use strdup:
M->foldedSeq = strdup( M->seq ) ;

Related

Strange behaviour in C program, variable corruption after allocating memory

I have typdef of string in my C program, it looks like that:
#define WRD_LEN 100
typedef char cstring[WRD_LEN];
then at some point I declare dynamic array of this type:
int pcount = 1;
cstring *options = malloc(sizeof(cstring*)*pcount);
I add new strings to this array with use of realloc:
options = realloc(options, sizeof(cstring*)*pcount);
strcpy(options[pcount-1], //some string//);
pcount++;
and then show all entries to user, user choses one of them and that one is passed to another function:
highestof(mode, l, options[btn]);
mode is an integer, l is struct but those are irrelevant now. btn is number (int) of entry chosed by user.
Up to this point everything works just fine, problem shows up inside highestof function:
void highestof(const int mode, List l, const cstring cat) {
List *p = malloc(sizeof(List*));
here is definition of List:
struct W {
//some data
struct W *next;
};
struct List {
struct W *first;
};
So if highestof function is called with options[1], cat variable will get corrupted (it will became a set of few random symbols, like "#^?" or "^K^?") right after malloc is called i.e. before creating dynamic array of List I can use cat as much as I want, but after calling malloc it gets corrupted. Most strange thing about this is that it happens only if variable passed down to this function was in options array under index of 1 (options[btn] where btn = 1) For any other value of btn it works no problem.
I found a workaround for this, I can create a string (char s[100]) before calling malloc, copy cat value into it and use that variable instead, but it's really not resolving initial problem and it really bothers me.
sizeof(cstring*)*pcount is too small. The size calculation is amiss.
Avoid allocation errors. Use this idiom for code that is easier to write correctly, review and maintain.
Notice no type is used.
pointer = malloc(sizeof *pointer * n);
Then code becomes:
// options = malloc(sizeof(cstring*)*pcount);
options = malloc(sizeof *options * pcount);`
cstring* is just a pointer, usually four or eight bytes. sizeof (cstring*) is therefore a small number, usually four or eight.
You are not allocating enough memory for the data, just enough memory to hold pointers to the data.

Segmentation fault when trying to access a struct array

As part of an assignment, I have to deal with three structs. There is some larger table within a file, FileHeader, that is made up of SectionHeader structs. Hdr is made up of an array of these structs laid out in contiguous memory. As a result, I should be able to access the array by typecasting the location of the table in memory.
typedef struct {
unsigned int offset; // offset in bytes from start of file to section headers
unsigned short headers; // count of section headers in table
} FileHeader;
typedef struct {
unsigned int name;
unsigned int type;
} SectionHeader;
I am supposed to: Use the offset and headers fields from the FileHeader (hdr) to identify the location and length of the section header table. I have assumed the start of the file is &hdr.
So I did this, but it is giving me a seg-fault. What is the proper way to access this array?
int header_location = hdr.offset;
int header_length = hdr.headers;
SectionHeader *sec_hdrs = (SectionHeader *) &hdr + header_location;
SectionHeader sec_hdr;
for (int i = 0; i < header_length; i++) {
sec_hdr = sec_hdrs[i];
if (sec_hdr.type == SHT_SYMTAB) break;
}
Try this: ElfSectionHeader *sec_hdrs = (ElfSectionHeader *)((unsigned char *) &hdr + header_location);
Your orinal code &hdr + header_location would offset the pointer by sizeof(hdr) * header_location which is not your intention.
You declared sec_hdrs as a pointer to SectionHeader. It is not an array and it can't be indexed. Your compiler should raise a warning.
Try this:
SectionHeader hdrs[header_length]
int header_location = hdrs[0].offset;
int header_length = hdrs[0].headers;
SectionHeader *sec_hdrs = hdrs + header_location;
SectionHeader sec_hdr;
for (int i = 0; i < header_length; i++) {
sec_hdr = sec_hdrs[i];
if (sec_hdr.type == SHT_SYMTAB) break;
}
Here is a visualization of the memory with an initial offset followed by SectionHeader's placed in contiguous memory.
header_location | sizeof(SectionHeader)| sizeof(SectionHeader) | sizeof(SectionHeader)
vijairaj makes a very valid point about a possible bug in your code.
Your original code &hdr + header_location would offset the pointer by
sizeof(hdr) * header_location which is not your intention.
This is a valid diagnosis and you should investigate how pointer arithmetic works. We increment the address by the size of its type. Once you are sure that *sec_hdrs is pointing to the correct place, rerun your program. If the segfault persists, try my next piece of debugging advice.
Yes, on other questions here, I have seen that you might have to malloc first. But I do not understand why that is necessary if you have a pointer to the array if you know that it is in contiguous memory, and also how to do this.
Just because we know something is in contiguous memory does not mean it is safe from being overwritten or reused by our program. That is the point of malloc - to protect certain blocks of memory from being overwritten. If you access unallocated memory, you run the risk of accessing sensitive data, overwriting program-dependent data, or storing data that will get overwritten. This is why a segfault will occur and this is why you need to malloc.
Ensure that you malloc enough space:
malloc(header_location + header_length * sizeof(SectionHeader))
This line of code is saying, "Please allocate contiguous memory for one offset and n SectionHeader's". The malloc call will return a pointer to the start of that memory block (&hdr) and then you may access anything within that block of memory.
Perhaps include the code that is providing you with &hdr? Hope this is helpful!

C - Append strings until end of allocated memory

Let's consider following piece of code:
int len = 100;
char *buf = (char*)malloc(sizeof(char)*len);
printf("Appended: %s\n",struct_to_string(some_struct,buf,len));
Someone allocated amount of memory in order to get it filled with string data. The problem is that string data taken from some_struct could be ANY length. So what i want to achieve is to make struct_to_string function do the following:
Do not allocate any memory that goes outside (so, buf has to be allocated outside of the function, and passed)
Inside the struct_to_string I want to do something like:
char* struct_to_string(const struct type* some_struct, char* buf, int len) {
//it will be more like pseudo code to show the idea :)
char var1_name[] = "int l1";
buf += var1_name + " = " + some_struct->l1;
//when l1 is a int or some non char, I need to cast it
char var2_name[] = "bool t1";
buf += var2_name + " = " + some_struct->t1;
// buf+= (I mean appending function) should check if there is a place in a buf,
//if there is not it should fill buf with
//as many characters as possible (without writting to memory) and stop
//etc.
return buf;
}
Output should be like:
Appended: int l1 = 10 bool t1 = 20 //if there was good amount of memory allocated or
ex: Appended: int l1 = 10 bo //if there was not enough memory allocated
To sum up:
I need a function (or couple of functions) that adds given strings to the base string without overwritting base string;
do nothing when base string memory is full
I can not use C++ libraries
Another things that I could ask but are not so important right now:
Is there a way (in C) iterate through structure variable list to get their names, or at least to get their values without their names? (for example iterate through structure like through array ;d)
I do not normally use C, but for now I'm obligated to do, so I have very basic knowledge.
(sorry for my English)
Edit:
Good way to solve that problem is shown in post below: stackoverflow.com/a/2674354/2630520
I'd say all you need is the standard strncat function defined in the string.h header.
About the 'iterate through structure variable list' part, I'm not exactly sure what you mean. If your talking about iterating over the structure's members, a short answer would be : you can't introspect C structs for free.
You need to know beforehand what structure type you're using so that the compiler know at what offset in the memory it can find each member of your struct. Otherwise it's just an array of bytes like any other.
Don't mind asking if I wasn't clear enough or if you want more details.
Good luck.
So basically I did it like here: stackoverflow.com/a/2674354/2630520
int struct_to_string(const struct struct_type* struct_var, char* buf, const int len)
{
unsigned int length = 0;
unsigned int i;
length += snprintf(buf+length, len-length, "v0[%d]", struct_var->v0);
length += other_struct_to_string(struct_var->sub, buf+length, len-length);
length += snprintf(buf+length, len-length, "v2[%d]", struct_var->v2);
length += snprintf(buf+length, len-length, "v3[%d]", struct_var->v3);
....
return length;
}
snprintf writes as much as possible and discards everything left, so it was exactly what I was looking for.

Using malloc with a structure and strcpy

I'm attempting to make an array of the structure I made called StatusItem, which looks like this:
typedef struct
{
char* name;
char* index;
int optional;
} StatusItem;
Also, as I want this array to be of any size, I am using malloc. So the array is defined as such:
StatusItem* statusItem = NULL;
(its then passed to function which retrieves all the values as follows.)
statusItem = (StatusItem*)malloc(cJSON_GetArraySize(items));
...
for (i = 0 ; i < cJSON_GetArraySize(items) ; i++)
{
strcpy(statusItem[i].name,name->valuestring);
strcpy(statusItem[i].index,index->valuestring);
if(!parseInt(optional->valuestring, &statusItem[i].optional));
{
goto cleanup;
}
}
There's come code that involves the cJSON library in getting the string values of name, index and optional into the variables referenced above, and they are stored in the valuestring field of those variables.
I have checked that everything involving the cJSON library works fine, and returns the correct values, but the program is unable to access or store values in the statusItems array.
Any ideas? I'm almost positive that it involves some misuse of malloc on my part.
1) cJSON_GetArraySize(items) returns an element count - you need the size of the object factored in: malloc(cJSON_GetArraySize(items) * sizeof(StatusItem))
2) a StatusItem structure doesn't have memory for the actual string - only a pointer to a string. You can use strdup() to allocate and copy a string.
You probably want your code to look more like:
statusItem = (StatusItem*)malloc(cJSON_GetArraySize(items) * sizeof(StatusItem));
...
for (i = 0 ; i < cJSON_GetArraySize(items) ; i++)
{
statusItem[i].name = strdup(name->valuestring);
statusItem[i].index = strdup(index->valuestring);
if(!parseInt(optional->valuestring, &statusItem[i].optional));
{
goto cleanup;
}
}
Of course this means that you also have to free the duplicated strings explicitly when you free the array of StatusItem objects:
// to free the statusItem array, and the various strings it refers to:
for (i = 0 ; i < cJSON_GetArraySize(items) ; i++)
{
free(statusItem[i].name);
free(statusItem[i].index);
}
free(statusItem);
Two misuses spotted:
Don't cast the return value of malloc(), it's dangerous and superfluous.
You don't allocate any memory for the members of the structure - you're strcpy()ing to uninitialized pointers, so your program invokes undefined behavior.
Edit: actually three:
malloc(cJSON_GetArraySize(items));
doesn't allocate enough memory since it's not magic and it doesn't know you're reserving sizeof(StatusItem) bytes of memory, thus you have to multiply the allocation size by sizeof(StatusItem), or even better, by sizeof(*statusItem) for safety.
In addition, malloc takes a number of bytes, not elements. The value passed to it must be multiplied by the size of each element.
To avoid having to use strdup() which is a little 'messier' because it leaves the freeing of the memory up to the caller instead of taking care of everything itself, I modified my existing structure as follows:
typedef struct
{
char name[32];
char index[32];
int optional;
} StatusItem;
This allows 32 bytes for the name and index, which should be more than enough. Before, the structures fields were pointing to nothing, which was causing the error when trying to copy to that location. now, there is empty (or junk) memory waiting for the string to be placed in.
This allows for strcpy() to still be used, and allows for an overall cleaner implementation.

Copy two structs in C that contain char pointers

What is the standard way to copy two structs that contain char arrays?
Here is some code:
#include stdio.h>
#include string.h>
#include stdlib.h>
typedef struct {
char* name;
char* surname;
} person;
int main(void){
person p1;
person p2;
p1.name = (char*)malloc(5);
p1.surname = (char*)malloc(5);
strcpy(p1.name, "AAAA");
strcpy(p1.surname, "BBBB");
memcpy(&p2, &p1, sizeof(person));
free(p1.name);
printf("%s\n", p2.name);
return 0;
}
The line printf("%s\n", p2.name); does not print something, because I freed the buffer.
The problem with my structs is that they are bigger than struct person. They contain hundreds of char pointers, and I have to copy every member one by one.
Is there another way to copy two structs that contain char arrays without using malloc and strcpy for every member?
You have no choice but provide a copy function yourself:
void copy_person(person *dst, const person *src)
{
dst->name = malloc(strlen(src->name) + 1);
dst->surname = malloc(strlen(src->surname) + 1);
strcpy(dst->name, src->name);
strcpy(dst->surname, src->surname);
}
which may be more elaborated than that: checking for errors, factoring the strlen + strcpy in an auxilliary function, etc.
That's what copy constructors in C++ are for.
Yes, copying struct that contain char arrays will work without any problem, but struct with char pointers (or any type of pointer for that matter) you will have to do manually.
Also note that the cast of malloc's return type is not needed in C (it is in C++) and can hide a missing prototype for malloc.
To elaborate on the answer of Alexandre C. you might want to do the malloc() as a single operation so that a free() is also simple.
This approach provides a degree of protection in that the single malloc() will either succeed or fail so that you would not have a problem of malloc() failing midway through constructing a copy. With this approach you would mix person with pointers to person that have been malloced so you might want to have two different data types something along the lines of the following in order to better mark which is which.
I have provided two alternatives for the copying with one using C Standard library functions strcpy() and strlen() and the other using a simple function that does a straight copy and returns a pointer to where it left off in the destination buffer.
I have not tried to compile this example so there may be problems with it.
There is one possible concern with this approach. Since the individual strings are not malloced you may run into a problem if you are moving the individual strings around using their pointers with the idea that each of the individual strings is its own malloced area of memory. This approach assumes the entire object is wanted or none of it is wanted.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
char* name;
char* surname;
char* address1;
} person, *personptr;
// copy a string to destination string return pointer after end of destination string
char * StrCpyRetEnd (char *pDest, char *pSrc)
{
while (*pDest++ = *pSrc++);
return pDest;
}
personptr DeepCopyPerson (person *pSrc)
{
personptr pDest = 0;
unsigned int iTotalSize = sizeof(person);
iTotalSize += (strlen(pSrc->name) + 1) * sizeof(char);
iTotalSize += (strlen(pSrc->surname) + 1) * sizeof(char);
iTotalSize += (strlen(pSrc->address1) + 1) * sizeof(char);
pDest = malloc(iTotalSize);
if (pDest) {
#if 1
// alternative one without a helper function
pDest->name = (char *)(pDest + 1); strcpy (pDest->name, pSrc->name);
pDest->surname = pDest->name + strlen(pDest->name) + 1; strcpy (pDest->surname, pSrc->surname);
pDest->address1 = pDest->surname + strlen(pDest->surname) + 1; strcpy (pDest->address1, pSrc->address1);
#else
// alternative two using StrCpyRetEnd () function
pDest->name = (char *)(pDest + 1);
pDest->surname = StrCpyRetEnd (pDest->name, pSrc->name);
pDest->address1 = StrCpyRetEnd (pDest->surname, pSrc->surname);
strcpy (pDest->address1, pSrc->address1);
#endif
}
return pDest;
}
int main(void){
person p1; // programmer managed person with separate mallocs
personptr p2; // created using ClonePerson()
p1.name = malloc(5);
p1.surname = malloc(5);
p1.address1 = malloc(10);
strcpy(p1.name,"AAAA");
strcpy(p1.surname,"BBBB");
strcpy(p1.address1,"address1");
p2 = DeepCopyPerson (&p1);
free(p1.name);
printf("%s\n", p2->name);
free (p2); // frees p2 and all of the memory used by p2
return 0;
}
You have to allocate memory to any pointer if you want to do a copy. However you can always make a pointer point to already allocated memory. For example, you can do the following:
p2.name = p1.name (p1.name is already allocated memory)
This is dangerous as there are more than one reference to the same memory location. If you free either p1.name or p2.name, it results in a dangerous situation.
In order to copy the entire content you have to allocate memory to the pointers of the struct p2.
p2.name = <allocate memory>
Copy individual struct members instead of a memcpy of the entire struct
This is because memory is not allocated in a contiguous manner. Also sizeof(struct) will give you size of the members of the struct and not the memory allocated to it.
For example sizeof(p2) = 8 = sizeof(p1)= sizeof(person) even after allocating memory to members of p1.
It would be a different case had the members been char arrays.
A bit out-of-the-box thinking:
Since the structure of your struct is static, you could write a small utility program or script to generate the copy code for you.
Take the source-code of your struct definition as input, and then devise a set of rules to generate the copying code.
This is quickshot, and I don't know if it were faster to just write the copy-code manually - but at least it is a more interesting problem.

Resources