I have some odd behaviour going on in my code which seems to be resulting from the use of a generic pointer though really I am totally uncertain. I have a fairly standard struct which looks like the following:
typedef struct {
char* name;
PyAutoCFunc ac_func;
void (*func)();
PyAutoType type_id;
int num_args;
PyAutoType arg_types[MAX_ARG_NUM];
} func_entry;
static func_entry* func_entries;
I am storing a static pointer to an array of these struct elements which is allocated on the heap. At the point where I create a new element of this array and insert it, its values look like this...
func_entry new_fe;
new_fe.name = malloc(strlen(name) + 1);
strcpy(new_fe.name, name);
... // Init rest of struct
func_entries[num_func_entries] = new_fe;
num_func_entries++;
func_entry* fe = &func_entries[num_func_entries-1];
printf("Setting function '%s' at address '%p', name address '%p'\n", name, fe, fe->name);
This outputs.
>>> Setting function 'graphics_viewport_set_title' at address '0xfe2d40', name address '0xe40fe0'
Notice the size and value of fe->name. I then store this pointer into a hashtable to retrieve later. In the hashtable this is stored as a simple void*. Later when I retrieve the pointer from the hashtable an odd thing happens.
func_entry* fe = PyAutoHashtable_Get(func_table, c_func_name);
printf("Getting function '%s' at address '%p', name address '%p'\n", c_func_name, fe, fe->name);
Which outputs.
>>> Getting function 'graphics_viewport_set_title' at address '0xfe2d40', name address '0x6e6f74656c656b73'
The address of fe has clearly been in and out of the hashtable without issue, but the size and address of fe->name has changed. Even more weirdly is that fe->name is a different size to what it was before and even a different size to fe. Trying to access fe->name gives me a segfault and I am unsure how to proceed.
Out of interest this seems to occur when I use the code in an application with several linked libraries, I'm fairly sure all the code I'm running is 64 bit.
I have run the above code successfully in a separate application and get a correct pointer for fe->name (a smaller one).
I am also running on Ubuntu Linux 64 bit and compiling with gcc.
This is really where my C ignorance shines though as I imagine it could be a million things. Can anyone shine some light?
That address for name looks like the result of memory corruption. It's completely unaligned, which is unlikely for an address returned by strdup off the heap.
It looks like you're out of scope for the structure you created. You mentioned it's created on the heap, but in the code it looks like it's probably created on the stack. This isn't all being done in the same function, is it? Is the code in the first block in a function that's existed before running the code in the later block? As soon as you exit that function the memory for that structure ceased to be, even though you retained a pointer to it. Later, when you pulled the pointer out of the hash table the memory had been overwritten and didn't have the pointer to name there anymore. If you're going to pass around pointers to structures allocate them dynamically by using malloc. They're exist until you explicitly get rid of them using free, instead of when the function ends.
Pointers always are of the same size whether its a pointer to a struct or a generic pointer (char * in olden days, void * in ANSI standard.)
Here's a simple example I whipped out so that you could understand structures, pointers (not in detail though but you get the idea.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person {
char *name;
int age;
};
void print(void *);
int main()
{
struct person *david;
if ((david = (struct person *)malloc(sizeof(struct person))) != NULL) {
david->name = strdup("David");
david->age = 40;
printf("sizeof david = %d, sizeof person = %d\n", sizeof david,
sizeof(struct person));
print((void *)david);
}
}
void print(void *p)
{
struct person *pp = (struct person *)p;
printf("sizeof p = %d, sizeof pp = %d\n%s %d\n", sizeof p, sizeof pp,
pp->name, pp->age);
}
Output
sizeof david = 8, sizeof person = 16
sizeof p = 8, sizeof pp = 8
David 40
Hope that helps.
It certainly looks as if something is writing over that data structure. The pointer value 0x6e6f74656c656b73 which you are seeing looks very suspicious indeed - it is ASCII for "noteleks", which is "skeleton" backwards. Perhaps this might give you an idea of what is overwriting your data.
Related
I am writing a program that has a bigger struct and a smaller struct, the smaller one holding names of friends of the person in index 0 of a 2D array in Friends. I wrote the whole thing from scratch a few times and it keeps giving me either seg fault or Thread 1: EXC_BAD_ACCESS (code=1, address=0x0).
Here are my structs:
expandBig() and expandFriends() do not assign values to the new data.
Looks like at least a problem is name assignment.
friends->name[friends->size] is not assigned a value after expandFriends(friends), so strcpy() fails.
void addFriend(Friends * friends, char * val) {
if(friends->size == friends->cap)
expandFriends(friends);
strcpy(friends->name[friends->size], val);
....
Consider using strdup()
// strcpy(friends->name[friends->size], val);
friends->name[friends->size] = strdup(val);
... and in InitializeFriends()
friend->name[i] = NULL;
Code such as below is tedious to review.
Was the size right? IDK, now have to trudge up to friend, find its type. OK that is Friends. Now look for Friends definition and see member char ** name. OK, now with char ** de-referenced we get char *. That matches codes sizeof(char*), so sizeof(char*) OK.
friend->name = realloc(friend->name, sizeof(char*) * friend->cap);
Save time. Code to the size of the de-referenced pointer, not the type. This is easier to code right, review and maintain.
Was the size right?
Yep, by construction, sizeof *(friend->name) is the right size.
// friend->name = realloc(friend->name, sizeof(char*) * friend->cap);
friend->name = realloc(friend->name, sizeof *(friend->name) * friend->cap);
// People * ret = (People*)calloc(DEFAULT_CAP, sizeof(People));
People * ret = calloc(DEFAULT_CAP, sizeof *ret);
Unclear why code sometimes casts the return from a *alloc() call and sometimes did not. The cast is not needed.
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.
I am C novice but been a programmer for some years, so I am trying to learn C by following along Stanford's course from 2008 and doing Assignment 3 on Vectors in C.
It's just a generic array basically, so the data is held inside a struct as a void *. The compiler flag -Wpointer-arith is turned on so I can't do arithmetic (and I understand the reasons why).
The struct around the data must not know what type the data is, so that it is generic for the caller.
To simplify things I am trying out the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
void *data;
int aindex;
int elemSize;
} trial;
void init(trial *vector, int elemSize)
{
vector->aindex = 0;
vector->elemSize = elemSize;
vector->data = malloc(10 * elemSize);
}
void add(trial *vector, const void *elemAddr)
{
if (vector->aindex != 0)
vector->data = (char *)vector->data + vector->elemSize;
vector->aindex++;
memcpy(vector->data, elemAddr, sizeof(int));
}
int main()
{
trial vector;
init(&vector, sizeof(int));
for (int i = 0; i < 8; i++)
{add(&vector, &i);}
vector.data = (char *)vector.data - ( 5 * vector.elemSize);
printf("%d\n", *(int *)vector.data);
printf("%s\n", "done..");
free(vector.data);
return 0;
}
However I get an error at free with free(): invalid pointer. So I ran valgrind on it and received the following:
==21006== Address 0x51f0048 is 8 bytes inside a block of size 40 alloc'd
==21006== at 0x4C2CEDF: malloc (vg_replace_malloc.c:299)
==21006== by 0x1087AA: init (pointer_arithm.c:13)
==21006== by 0x108826: main (pointer_arithm.c:29)
At this point my guess is I am either not doing the char* correctly, or maybe using memcpy incorrectly
This happens because you add eight elements to the vector, and then "roll back" the pointer by only five steps before attempting a free. You can easily fix that by using vector->aindex to decide by how much the index is to be unrolled.
The root cause of the problem, however, is that you modify vector->data. You should avoid modifying it in the first place, relying on a temporary pointer inside of your add function instead:
void add(trial *vector, const void *elemAddr, size_t sz) {
char *base = vector->data;
memcpy(base + vector->aindex*sz, elemAddr, sz);
vector->aindex++;
}
Note the use of sz, you need to pass sizeof(int) to it.
Another problem in your code is when you print by casting vector.data to int*. This would probably work, but a better approach would be to write a similar read function to extract the data.
If you don't know the array's data type beforehand, you must assume a certain amount of memory when you first initialize it, for example, 32 bytes or 100 bytes. Then if you run out of memory, you can expand using realloc and copying over your previous data to the new slot. The C++ vector IIRC follows either a x2 or x2.2 ratio to reallocate, not sure.
Next up is your free. There's a big thing you must know here. What if the user were to send you a memory allocated object of their own? For example a char* that they allocated previously? If you simply delete the data member of your vector, that won't be enough. You need to ask for a function pointer in case the data type is something that requires special attention as your input to add.
Lastly you are doing a big mistake at this line here:
if (vector->aindex != 0)
vector->data = (char *)vector->data + vector->elemSize;
You are modifiyng your pointer address!!! Your initial address is lost here! You must never do this. Use a temporary char* to hold your initial data address and manipulate it instead.
Your code is somewhat confusing, there's probably a mis-understanding or two hiding in there.
A few observations:
You can't change a pointer returned by malloc() and then pass the new value to free(). Every value passed to free() must be the exact same value returned by one of the allocation functions.
As you've guessed, the copying is best done by memcpy() and you have to cast to char * for the arithmetic.
The function to append a value could be:
void add(trial *vector, const void *element)
{
memcpy((char *) vector->data + vector->aindex * vector->elemSize, element);
++vector->aindex;
}
Of course this doesn't handle overflowing the vector, since the length is not stored (I didn't want to assume it was hard-coded at 10).
Changing the data value in vector for each object is very odd, and makes things more confusing. Just add the required offset when you need to access the element, that's super-cheap and very straight forward.
I have the following structs as example:
#define MAX_PEOPLE 16
typedef struct {
int age;
}Person;
typedef struct {
Person *people;
int numPeople;
}Team;
I'm trying to allocate an array of persons in a function, passed by parameters. My Team is supposed to store an array of 16 pointers of Person. I can't figure out what I'm doing wrong.
void initiateTeam(Team * team){
team->numPeople = MAX_PEOPLE;
Person *p[MAX_PEOPLE];
for(int i=0; i<MAX_PEOPLE;i++){
p[i] = malloc(sizeof(Person);
}
team->people = &p[0];
}
I printed out the addresses of my team->people[i] and I'm getting random junk. Why is the assingment team->people = &p[0] wrong? Shouldn't it get the first address of my array then perform pointer arithmetic?
You are pointing team->people to a statically defined array of person pointers. Once the function ends, the stack pointer moves back to where main left off, erasing all previously local memory in the addPeople function. You need to malloc p, and return it from the function
Since in the comments you stated that you're trying to allocate an array of Person objects and not pointers, you should rather do:
void addPeople(Team * team){
team->numPeople = MAX_PEOPLE;
team->people = malloc(sizeof(Person) * MAX_PEOPLE);
}
mind that there's no * in sizeof since you don't want an array of pointers but of objects. You will later be able to access the single elements (i.e. each Person object) with
team->people[2].age = 25; // The third person in the array
Finally, remember to free your memory.
your variable p is allocated in the stack of the addPeople() function. The assignment team->people = &p[0] (which is equivalent to team->people = p) is valid but dangerous because that address will be invalid as soon as the function is finished.
Better create p with malloc(sizeof (Person *) * MAX_PEOPLE) instead of using the stack.
The problem is here:
Person *p[MAX_PEOPLE];
This allocates a local variable in the function to hold the array of people pointers.
You get the address of this local variable and send it back. As soon as you are not in the function the local data is freed. It was just allocated locally. It is no longer valid. I might work for a while or it might not depending on the the program does next.
You want this:
Person **p = (Person **)malloc(sizeof (Person *) * MAX_PEOPLE);
I think you are getting the thing with pointer and memory management in C a little bit wrong. Consider reading a little bit more about it, before you continue coding your application.
Beside, I think you do not need an array of pointers to persons, but an array of persons.
Your struct is correct, but I would implement your function like that:
void addPeople(Team * team){
team->numPeople = MAX_PEOPLE;
team->people = malloc(sizeof(Person) * MAX_PEOPLE);
}
And do not forget to free() your team->people.
But if MAX_PEOPLE is an pre processor define, then it is totally unnecessary to use memory from the heap. If you are not storing too many people in your struct, the stack can easily fulfill your requirements.
I have a question regarding this code. I write this code in my framework, and it caused the framework crashed. But when I rewrite this code below in a single file, but it works just fine. I was just wondering, is the code below is correct for memory allocation and freeing it? (especially for the part of msg->context_var.type = f;)
Thank you
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int value;
int price;
int old;
} type_t;
typedef struct {
type_t *type;
} context_t;
typedef struct {
context_t context_var;
} send_request;
void send_Message(send_request *msg)
{
type_t *f = 0;
f = malloc(sizeof(f));
msg->context_var.type = f;
msg->context_var.type->price = 1;
msg->context_var.type->value = 100;
msg->context_var.type->old =120;
printf("value of %d/n", msg->context_var.type->price);
free(f);
}
int main()
{
send_request *msg = 0;
msg = (send_request *) malloc(sizeof(send_request));
send_Message(msg);
free(msg);
return 0;
}
It's wrong.
f = malloc(sizeof(f)); /* Wrong */
f = malloc(sizeof(*f)); /* Better ? */
sizeof(f) will give you the size of a pointer on your machine; sizeof(*f) will give you the size of the object pointed to.
EDIT As requested by #Perception
When you allocate less than you need you're eliciting Undefined Behavior. Anything can happen (even the desired behavior) and it all depends on the platform, the environment (the moon phase, etc).
msg->context_var.type->value = 100; /* Writes beyond what's allocated. */
So, depending on the memory layout of the "framework" this might simply overwrite some memory and "work", or it could crash. Frankly I prefer when it crashes straight away.
You allocate an instance of context_t on the heap, and then msg->context_var.type gets the value of the resulting pointer f.
Since msg is a pointer parameter to the send_Message function, no reliable assumptions can be made about what is done with msg and its contents after your function exists. As such, when you go on to free the memory pointed to by f, you leave a dangling pointer in msg->context_var.type.
If the memory it points to is accessed after send_Message exists, there's a fair chance that you corrupt something vital (or read something crazy, like a pointer to 0xdeadbeef), as it might contain something completely different now.
Not only are you allocating wrong size (see cnicutar's answer)-- If you are attaching f to message that is passed by the framework, you probably don't want to free it before the function returns. You'll need to free it later, though-- probably through some other facility provided by the framework?