I am having a problem with creating a function that will add (copy) structure from parameter to resized array.
Here is my simplified code:
typedef struct User
{
char FirstName[32];
char LastName[32];
}
User;
User * Users
unsigned short UsersNum = 0;
void AddUser(User * NewUser)
{
Users = (User *) realloc(Users, (UsersNum + 1) * sizeof(User));
memcpy(Users[UsersNum], NewUser, sizeof(User));
UsersNum++;
}
With this I'm getting:
error: incompatible type for argument 1 of `memcpy'
I've also tried
memcpy(Users + UsersNum, NewUser, sizeof(User));
But got SEGFAULT.
How can i copy NewUser to the end of Users?
First, please don't cast the return value of malloc() in C.
Second, why do you feel you must use memcpy() here? The memcpy() function is great, but it's a rather blunt tool meant to "blindly" copy large areas of memory that have no further structure that the program is aware of. In your case, you know that the bytes you're copying make up an instance of the User type, i.e. it's simply a value of type User.
Values are typically moved around by assignment, so use that instead:
void AddUser(const User *NewUser)
{
User *UsersGrown = realloc(Users, (UsersNum + 1) * sizeof *Users);
if(UsersGrown != NULL)
{
Users = UsersGrown;
Users[UsersNum] = *NewUser;
++UsersNum;
}
}
You can see that I also made the argument const, and added some basic error-checking since realloc() can fail.
It would be a good idea to separate the allocated size of the Users array from the length of the array, so that you can grow them at different speeds and cut down on the number of calls to realloc(). In other words, allocate room for e.g. 8 elements at first, and when that is hit, double the size and realloc(), and so on. This gives much better performance if you expect many insertions.
You should ask yourself what type is User[UsersNum] ... that is User, and memcpy operates on pointers. To get address of it there is & operand. So it should be
memcpy(&Users[UsersNum], NewUser, sizeof(User));
Also please note the you are using very very inefficient way to implement the functionality. Copying/moving stuff around so much should be avoided.
Related
I often find myself spending a lot of time figuring out how I should properly size a malloc when I have a non-obvious type. Here is an example:
typedef struct {
char* key;
char* value;
} hash_item;
typedef struct {
int size; // max size of the table
int count; // how many items are currently in the table
hash_item** items; // will have size * hash_items in the array
} hash_table;
Now, when I create a new hashtable, I'll do something like this:
hash_table *table = malloc(sizeof(hash_table));
table->items = malloc(sizeof(*hash_item) * size); // this is tricky for me
Is that 'sizing' correct? And how do I know that sizeof(*hash_item) is the correct unit-size, and not for example:
sizeof(hash_item)
sizeof(table->items[0])
sizeof(*(table->items))
Is there a good rule of tumb for how to size a malloc when it's referring to a non-primitive data-type?
You generally do not need to use types in the malloc size, and you should avoid it. You can use a “sample object” instead:
PointerToThing = malloc(NumberOfThings * sizeof *PointerToThing);
So that is very simple: *PointerToThing is the type of thing being pointed to, so its size is what you want.
Further, it reduces the chances of certain errors:
If you try typing a type description for what PointerToThing points to, you can make a mistake. *PointerToThing is simple, so people are less likely to make a mistake with it, especially once it becomes habit.
If you are modifying the program in the future and change the type of PointerToThing, you have to remember to also search for everywhere that type is used and change it there too. With the method above, the type does not appear, so it cannot be overlooked—there is no change to make when the type changes; the sizeof adapts automatically to whatever type *PointerToThing is.
And PointerToThing does not have to be a simple variable. It can be an expression, such as table->items, for which you could use malloc(NumberOfItems * sizeof *table->items).
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 creating a symbol table for a compiler I am writing and when I try adding to my symbol table I keep getting valgrind errors. When I call my function, I am calling my add function
stAdd (&sSymbolTable, "test", RSRVWRD, 4, 9);
and in my stAdd function it is currently
void stAdd (StPtr psSymbolTable, char *identifier, SymbolTableType type,
int addressField, int arrayDimensions)
{
int hashValue;
hashValue = hash (identifier, psSymbolTable->numBuckets);
if (psSymbolTable->spSymbolTable[hashValue] == NULL)
{
psSymbolTable->spSymbolTable[hashValue] = (StEntryPtr) malloc (sizeof(StEntry));
strcpy (psSymbolTable->spSymbolTable[hashValue]->identifier, identifier);
psSymbolTable->spSymbolTable[hashValue]->entryLevel = psSymbolTable->currentLevel;
psSymbolTable->spSymbolTable[hashValue]->type = type;
psSymbolTable->spSymbolTable[hashValue]->addressField = addressField;
psSymbolTable->spSymbolTable[hashValue]->arrayDimensions = arrayDimensions;
psSymbolTable->spSymbolTable[hashValue]->psNext = NULL;
}
}
But every time I set a value within my StEntry struckt, I get an error
Use of unitialised value of size 8
every time I set something within the if statement. Does any see where I am going wrong?
My StEntry is
typedef struct StEntry
{
char identifier[32];
SymbolTableLevel entryLevel;
SymbolTableType type;
int addressField;
int arrayDimensions;
StEntryPtr psNext;
} StEntry;
This would be a lot easier if I could see the definition of struct StEntry or even the precise valgrind error. But I'll take a wild guess anyway, because I'm feeling overconfident.
Here, you malloc a new StEntry which you will proceed to fill in:
psSymbolTable->spSymbolTable[hashValue] = (StEntryPtr) malloc (sizeof(StEntry));
This is C, by the way. You don't need to cast the result of the malloc, and it is generally a good idea not to do so. Personally, I'd prefer:
StEntry* new_entry = malloc(sizeof *new_entry);
// Fill in the fields in new_entry
psSymbolTable->spSymbolTable[hashvale] = new_entry;
And actually, I'd ditch the hungarian prefixes, too, but that's an entirely other discussion, which is primarily opinion-based. But I digress.
The next thing you do is:
strcpy (psSymbolTable->spSymbolTable[hashValue]->identifier, identifier);
Now, psSymbolTable->spSymbolTable[hashValue]->identifier might well be a char *, which will point to the character string of the identifier corresponding to this symbol table entry. So it's a pointer. But what is its value? Answer: it doesn't have one. It's sitting in a block of malloc'd and uninitialized memory.
So when strcpy tries to use it as the address of a character string... well, watching out for the flying lizards. (If that's the problem, you could fix it in a flash by using strdup instead of strcpy.)
Now, I could well be wrong. Maybe the identifier member is not char*, but rather char[8]. Then there is no problem with what it points to, but there's also nothing stopping the strcpy from writing beyond its end. So either way, there's something ungainly about that line, which needs to be fixed.
Im creating a web app and already working on the backend. I need to process a lot of post request data using C and API's provided in appweb.
Here's the code:
static void addStudentInformation()
{
char * average = malloc(30000);
MprJson * userInput = httpGetParams(getConn());
char * name;
strcpy(name,mprLookupJson(userInput, "name"));
average = computeGrade(mprLookupJson(userInput, "gradeSubject1_1"), mprLookupJson(userInput, "gradeSubject1_2"), mprLookupJson(userInput, "gradeSubject1_3"));
//more function calls
}
char * computeGrade(char * grade1, char * grade2, char * grade3)
{
/*process grade*/
return average;
}
//more function
As you can see, the value returned by mprLookupJson was directly used a a parameter in function computeGrade. I thought of not storing those values in a variable since it wont needed/ used in addStudentInformation. I thought that there's no point of alloting/using a memory. Now, my question is it safe/good practice to do that? is there any possibility that a security issue may arise because of that? What would be the best approach for this?
Thank you.
What happens if mpfLookupJson(userInput, "name") does not find a valid entry? Say, it delivers -1 as it has not found an entry. In that case, your strcpy() could crash.
If mpfLookupJson finds something valid, it will allocate some memory on the heap and give you the pointer to it. In that case, the memory has already been allocated. If you create a further pointer variable to it, in my opinion it won't matter. If you program some special micro controller, maybe you have to care about some bytes more or less, but probably not here.
Now you create a pointer variable name and try to copy the value found to where name points to. As long as you don't allocate memory for name to point to, this will crash. Further: do you really need a copy of the value found by mpfLookupJson? Can't you use it as it has been returned?
To my eyes, this would be enough, more reliable and more readable:
static void addStudentInformation()
{
char * average = malloc(30000);
MprJson * userInput = httpGetParams(getConn());
char * name;
char * grade1;
char * grade2;
char * grade3;
name = mprLookupJson(userInput, "name");
grade1 = mprLookupJson(userInput, "gradeSubject1_1");
grade2 = mprLookupJson(userInput, "gradeSubject1_2");
grade3 = mprLookupJson(userInput, "gradeSubject1_3");
if (name <= 0 || grade1 <= 0 || grade2 <= 0 || grade3 <= 0 ) {
// handle error and / or abort
}
average = computeGrade(grade1, grade2, grade3);
//more function calls
...
}
Then, what happens after the end of the function? If memory is important to you, make sure you deallocate everything the right way.
These are rather safety concerns than security concerns. Security starts where somebody can misuse your code to get admin privileges or make the process crash or the memory being flooded. The first points to examine would be what mprLookupJson precisely does, how good userInput has been filtered against tampering and how strict you react if name, grade1, grade2 etc. are invalid the slightest way. Alone for this reasons, you need well readable code.
Hope these suggestions are a good start :-)