I populated a structure(ORDER_EXPIRY_TP *OrderReqXml) and now I want to check whether structure conatains any value or not? Here is my code:
OrderReqXml->fIntOrderNumbe =at_int_ord_req->fIntOrderNumber;
OrderReqXml->dLocationCode = 0;
OrderReqXml->dQzUser = at_int_ord_req->dUserId
OrderReqXml->dSuperUserId = 0;
So basically i want 2 check whether OrderReqXml is null or not.
Really depends on what you are trying to achieve.
If you allocate your struct like this:
Order* OrderReqXml = malloc(...);
then, you should indeed check for the pointer being != NULL before assigning values to your struct. A good way would be:
Order* OrderReqXml = malloc(...);
if (OrderReqXml != NULL) {
// fill data
} else { /* error handling */ }
If you obtain the pointer from somewhere else, e.g. from a static structure in memory and you want to check whether the struct has been populated or not, you need to check the single struct elements:
bool structIsNotFilled(Order* o) {
return ((o->fIntOrderNumber == 0) &&
(o->dLocationCode == 0) &&
(o->dQzUser == 0) &&
(o->dSuperUserId == 0))
}
The question then is however, if you wanted to trust this struct in memory to be initialized with zeros. (You must not trust memory allocated with malloc() to be initialized to zero.)
Related
bool check(const char *word)
{
node* node_ptr = first;
for (int i = 0, len = strlen(word); i <= len; i++)
{
if(word[i] == '\0')
{
if (node_ptr->is_word == true)
return true;
else
return false;
}
int index = get_index(word[i]);
if (node_ptr->children[index] == NULL)
return false;
node_ptr = node_ptr->children[index];
}
return false;
}
This is the code line in question or atleast where the error msg is pointing me.
I never had this error before so I`m having alot of difficulties dealing with it.
A google search wasnt really helpfull either.
It's saying that the pointer variable node_ptr is null but you're trying to access a field inside the structure that is expected to be at the memory location, but the memory location is invalid (the pointer is not initialized to a valid value). You either need to make sure your code doesn't have a mistake that makes it end up with a null pointer as the process goes along, or you need to have it point to a valid memory location by setting it to a memory allocated the memory using new (if you're using C++) or malloc (which you can use in C or C++). It's also not clear what the variable "first" is here...that's probably part of the problem... hope this helps!
The aim of the following function consists to retrieve specifics information
by calling few functions which are returning gchar * (using glib for D-BUS object parsing).
get_param() will be used in another file to get and work with these values.
char * get_param(unsigned short ID)
{
char * value = NULL;
if(ID == 0x01)
{
value = get_revision(); // REV 04.012
}
else if(ID == 0x02)
{
value = get_pin(); // 0000
}
else if(ID == 0x03)
{
value = get_identifier(); // 690012345396789
}
else if(ID == 0x04)
{
value = get_number(); // 697132101234585233318
}
else if(ID == 0x05)
{
value = get_manufacturer(); // MANUFACTURER_1
}
else {}
return value;
}
I get the expected values in the final source file, but I will probably get bad behavior by returning
char * without memory allocation. In this specific case, data length isn't know in advance, so it is
better to allocate a size more bigger as necessary or not ? Should I define my function as returning void
type and include char ** in its arguments ?
EDIT : (to give more information)
I will take get_pin() function as example.
This function returns a gchar * which has been initialized by using gchar * output = g_strdup (g_variant_get_string(myVariant, NULL)). According to the gnome datasheet g_strdup returns a newly-allocated copy of myVariant.
Then, in the final function I would define an array as char value[50] and initialize it by using value = get_param(0x01)
In nowadays standards, you should use externally allocated memory, and length limit, like all the *_r functions do. See gethostbyname_r.
All other alternatives are lacking. If you allocate every time you force users to dealocate which is less than comfortable.
You allocate and reuse the same memory per thread but, in your case, since you're dealing with various return values, the contents of the memory would change under your clients feet so very unadvisable.
Using externally allocated memory also gives them the option to allocate the memory in other ways than plain malloc.
Currently you are returning a pointer to already allocated value, so there's no bad practice.
If you'd really want to allocate memory for theses pointers, you could do something like that :
...
char* returned_value = malloc(sizeof(char) * (strlen(value) + 1));
strcpy(returned_value, value);
return return_value;
Of course, you should trust that the value actually contains a \0 in a reasonnable length.
What I'm working on right now is a state-based parser for any input from a stream. My professor tells me this is the best way to avoid special cases. The way I've got it set up is using functions, and I'm having a little bit of trouble trying to reuse allocated memory so I don't cause any leaks. What I am parsing are multiple parameters. Each parameter has a name and a value. An example input would be:
parameterName = 500;
The name is parameterName and it is of type integer with a value of 500.
I am successfully able to parse one of these without memory leaks. However, doing a second parameter will cause leaks and I know why: It's the multiple uses of malloc on my parameter name.
Take a look at the parsing code:
int main()
{
int x;
char c;
char *nameTemp;
int hasName = 0;
int hasEqual = 0;
/* ParameterManager values */
ParameterManager *pm;
pm = PM_create(500);
if((PM_manage(pm, "name", INT_TYPE, 1)));
while((x = getchar()) != EOF)
{
/* Cast int to char */
c = (char)x;
/* Whitespace state */
if((isspace(c)))
{
c = whitespace();
}
/* Comment state */
if(c == '#')
{
c = comment();
}
/* Name state */
if(((isalnum(c)) && hasEqual == 0 && hasName == 0))
{
nameTemp = name(c);
printf("Name: %s\n", nameTemp);
hasName = 1;
}
/* Equal state */
if(c == '=' && hasName == 1 && hasEqual == 0)
{
hasEqual = 1;
}
/* Value state */
if((isalnum(c)) && hasName == 1 && hasEqual == 1)
{
getValues(c, nameTemp, pm->t_List, pm->m_List);
hasName = 0;
hasEqual = 0;
}
}
free(nameTemp);
if((PM_destroy(pm)) && DEBUG) printf("Success destroying PM.\n");
return 0;
}
The line nameTemp = name(c), under /* Name state */, returns an allocated string. This string is later passed to do other work. However, since this whole parsing idea is in a loop, multiple mallocs to the same string will be made. I can only free nameTemp once but there are multiple mallocs on that name. How can I reuse nameTemp over and over without causing any leaks?
Here is a piece of code (in function name()) where nameTemp is allocated:
/* Make sure temp is not NULL before mallocing */
if(temp[0] != '\0')
{
returnName = malloc(sizeof(char)*strlen(temp)+1);
strncpy(returnName, temp, strlen(temp)+1);
temp[0] = '\0';
return returnName;
}
I apologize if a few things are unclear. I'm trying to be as general as I can so if you need more clarification please let me know.
malloc() does not keep track of allocated blocks. You need to locate all the places where you're finished dealing with the memory you requested, and free() it there.
If I read your code correctly, that would be at the end of your while loop's body.
Edit : pulling up the comments.
It's undefined behaviour to try and use a block of memory that you already free()'d.
However, the pointer you use to keep a handle on the block is just a regular pointer, and won't go stale after you pass it to free(). In fact, it won't budge at all, since free() takes it by copy.
It is thus common to see said pointer set to NULL after it has been passed to free(), to ensure one does not accidentally reuse the now-unusable block.
You can then very well reuse it to be a handle on a brand new block returned by malloc(), as usual.
nameTemp = name(c); causes an inevitable leak, when nameTemp stores a pointer which is not saved somewhere else and is also not freed at this time.
There are quite a few options to avoid this (depends on what you are trying to achieve and how much you are willing to change your code structure).
Three possibilities (ordered from least amount of code change to most):
Free the memory before its assigned again (and free it again at the end of the program)
free(nameTemp);
nameTemp = name(c);
Free the memory when it becomes obsolete
/* Value state */
if((isalnum(c)) && hasName == 1 && hasEqual == 1)
{
getValues(c, nameTemp, pm->t_List, pm->m_List);
hasName = 0;
hasEqual = 0;
free(nameTemp);
nameTemp=NULL;
}
Use a general purpose buffer, allocate a big enough junk of memory at the beginning and free it at the end again.
char* nameTemp;
nameTemp = (char*)malloc(512); //Or any other size, just check that its actually big enough before writing to it, otherwise buffer overflow errors will occur.
// Somwhere in your program
write_name( nameTemp, 512 , c ); // Pass the buffer to be filled by the function, instead of returning a new pointer.
// At the end of your program
free(nameTemp);
nameTemp = NULL; //Prevent access of freed memory.
On RHEL6, I'm facing a strange problem with realloc(). At some point in the program, realloc() returns NULL (the old pointer has an address and there's plently of memory available). What's being allocated is 200 structure elements (structure below). For some reason, when I do a realloc() instead, it works, but I then have to assign the old pointer to the new one. Below is a simplified version of my code.
This is perhaps a server tuning issue more than a programming one. What is your opinion?
Thanks.
//hearder file
typedef struct { /* Variable Node Detail Record */
long next;
long mask;
char *value;
// more stuff...
} NODETEST;
extern NODETEST *oldNodes;
extern NODETEST *newNodes;
//program
#define MAXSIZE 200
// do some stuff with oldNodes....
int alloc_nodes (void)
{
// Allocate or grow the table
oldNodes = (NODETEST *) malloc(MAXSIZE * sizeof(NODETEST));
if( oldNodes == NULL ) {
//handle exception...
exit(1);
}
//oldNodes = (NODETEST *) realloc(oldNodes,MAXSIZE * sizeof(NODETEST)); // *** FAILS
newNodes = (NODETEST *) realloc(oldNodes,MAXSIZE * sizeof(NODETEST)); // *** WORKS
if( newNodes == NULL ){
printf("errno=%d\n", errno );
}else{
oldNodes = newNodes; }
}
Your first call malloc with a size S and then realloc with the same size S. This is wrong: you have to pass to realloc the new wanted size (independently of the current size - it is not an increment). Here, there is a big chance realloc returns exactly the same pointer it received. BTW it is not clear why you want to do with a malloc immediately followed by a realloc. Gives us more detail.
If you want a dynamic table whose size auto-adjusts, you need to allocate an initial size storing its size in a variable (e.g. alloc_size) and keep the current number of occupied elements in another variable (e.g. n_elem) . When you add an element you increment this number. When the table is full reallocate it. Here is a sketch
NODETEST *newNodes = NULL;
int allocated_elem = 0;
int n_elem = 0;
#define ALLOC_INCR 200
then at each addition:
if (n_elem >= alloc_size) { // the first time realloc is as malloc since nodes == NULL
alloc_size += ALLOC_INCR;
nodes = (NODETEST *) realloc(nodes, alloc_size * sizeof(NODETEST));
if (nodes == NULL) {
//handle exception...
exit(1);
}
}
// add your element at nodes[n_elem]
n_elem++;
Recall that realloc acts like malloc when the received pointer is NULL (case of the first call). Thus it allocates the initial table. Subsequent calls reallocate it by adjusting the size with a constant increment (here 200). Some other schemes are possible for the enlargement of the table, for instance you can multiply the size by a factor (e.g. 2) starting from 32:
if (n_elem >= alloc_size) { // the first time realloc is as malloc since nodes == NULL
alloc_size = (alloc_size == 0) ? 32 : alloc_size * 2;
Regarind the FAIL and WORKS comments: it is clear that if you assign oldNodes (in the FAIL code) then newNodes is not assigned and keeps its initial value which is zero (NULL) since it is declared as a global variable and not initialized (well I suppose, it is extern here). Thus the test if (newNodes == NULL) will probably fail.
I am new to C and I don't fully understand all this pointer and memory allocation stuff, so sorry if I am conceptually wrong. I am trying to access string elements in an array of strings, but the array of strings is located in a struct, and every time I try to access it my program crashes.
I am getting an error when I try to do this if statement check
if (strcmp(functionList[holder].otherServers[i], "") == 0)
I just want to check if the current structure element in the array of structs (functionList[holder]) has a empty value filled for its elements in its array of strings (otherServers[i]). And when it finds its first empty element, all I want to do is copy a string in that index of the array of strings (otherServers[i])
And here is my code (note: I took out a lot of the code I thought was irrelevant for the question)
struct function {
char name[20];
int parameterNumer;
int canDo;
//currently the system has a 10 server max. You can change this easily
char *otherServers[10];
};
//global scope variables
//currently the system has a 10 server max. You can change this easily
char *serverList[10];
struct function functionList[10] = {{"",0, 0, {}}};
int numberofOtherServers;
while(strcmp(functionList[i].name, "") != 0 && i != -1)
{
//if the function exist in the functionList already, then just add server to the functions list of capable servers
if(strcmp(functionList[i].name, functionName) == 0 && functionList[i].parameterNumer == functionParam)
{
holder = i;
//function found so go through the functions list of servers and add it to the list
i = 0;
while(i >= 0)
{
if(strcmp(functionList[holder].otherServers[i], "") == 0)
{
strcpy(functionList[holder].otherServers[i], serverHelloName);
i = -1; //
}
if(i == 9)
{ //ran through entire list of all possible servers and couldnt find an empty slot
printf("server list full, should allow more room for other servers");
fflush(stdout);
i = -1;
}
}
printf("yay");
fflush(stdout);
}
if(i == 9)
{ //ran through entire list of all possible functions and did not see an empty slot or there is no match
printf("function list full so could not add, and there was no match for any functions");
fflush(stdout);
i = -1;
}
i++;
}
Your code does not show allocation of otherServers. When you have an array of character pointers, like otherServers, you need to allocate memory for each of the strings so there is something to point to.
This means you need to check the pointer points somewhere valid before you can do this strcmp() and strcpy():
if(strcmp(functionList[holder].otherServers[i], "") == 0) {
strcpy(functionList[holder].otherServers[i], serverHelloName);
i = -1;
}
Instead this snippet will check that otherServers[i] hasn't already been allocated and then allocate enough memory to store the string:
if ( functionList[holder].otherServers[i] == NULL ) {
// add one for the terminator
functionList[holder].otherServers[i] = malloc(strlen(serverHelloName) + 1);
// make sure the allocation worked
if ( functionList[holder].otherServers[i] == NULL ) {
// something went wrong so bail
break;
}
strcpy(functionList[holder].otherServers[i], serverHelloName);
}
When you have finished with otherServers[] or functionList[] itself, you need to free the memory allocated earlier:
for ( i = 0; i < 10; i++ ) {
if ( functionList[holder].otherServers[i] != NULL ) {
free(functionList[holder].otherServers[i]);
functionList[holder].otherServers[i] = NULL;
}
}
It's better to put a NUL in place of a plain "" in an initializer:
struct function functionList[10] = {{{'\0'},0, 0, {}}};
To check whether the name in your example is then assigned or not, you just dereference it and check for the NUL character:
*functionList[i].name == '\0'
strcmp checks for a nul character (aka zero-terminator), beginning at the offset supplied, and will keep going beyond the array if it doesn't find one - resulting in undefined behaviour, most likely an access violation, depending on how this buffer was allocated.
SpacedMonkey beat me to the remainder of the valid answer; you need to allocate storage for a string. By default a pointer just points to some area in memory - you must allocate it by hand with malloc before using it, and release it using free.