c - mixing assignment and free() in a condition? - c

typedef char* string;
int func1(string s);
char* func2(); // returns a new memory/
if(func1(func2()) == 4)
{
// code
}
Assuming func2() is only needed in the condition. Since i need to free newly allocated memory, how can i free it up within the same line(i.e. with the same condition or paranthesis) ? My motiviton for this is to keep the code clean.
EDIT 1.
Yes it is a c question. The use of "string" type was error on my part as i have always typedef it to char*. Sorry for the confusion.

To do this cleanly, make a new function that does the work in a clear manner:
static int func3()
{
char *s = func2();
int result = func1(s);
free(s);
return result;
}
…
if (func3() == 4)
…
(Presumably, there is some assurance that func2 successfully allocates memory. If not, you must test its return value.)

Free it in the same line with no new function definitions:
int result;
char *temp;
/* comma operator: evaluate these 4 expressions left-to-right,
and the value is the value of the last expression */
if(temp = func2(), result = (func1(temp) == 4), free(temp), result)
{
/* Do things */
}
Cleaner code:
int func3(void)
{
char *temp;
int result;
temp = func2();
result = func1(temp);
free(temp);
return result;
}
/* ... */
if(func3() == 4)
{
/* do things */
}

Here is a solution using a functional approach:
int apply_free(int (*f1)(char*), char * (*f2)()) {
char *s = f2();
if (s != NULL) {
int result = f1(s);
free(s);
return result;
}
else {
return -1; /* or any meaningful value if f2 returned a NULL pointer */
}
}
if (apply_free(func1, func2) == 4)
{
// code
}
This assumes your various cases will have the same type signature.

Related

FORWARD_NULL Vs UNINIT Coverity errors in C

when a pointer is initialized to NULL, getting "FORWARD_NULL" coverity errors and when the NULL initialization is removed, it throws UNINIT coverity errors. The code is as below.
I am very new to coverity. If its a very basic question also, please help.
I am
1) declaring a pointer,
2) Initializing it to NULL and
3) deferring it without assigning anything to it.
This deference is an argument in a function call inside which, it will be filled in. Getting FORWARD_NULL errors for the same. Started with Coverity works, from yesterday only.
int fn1()
{
strct1 *pvarA = NULL;
if (fn2(&pvarA) != 0) // derefering NULL pointer error.
{
return 1;
}
...
/* some code */
}
int fn2(strct1 **pvarA)
{
...
/* some code */
*pvarA = varA;
/* some code */
return 0;
}
Thanks,
Preethi
In such code:
int fn1(int **ar)
{
int *a;
a = *ar;
}
The variable a is not initialized (thus UNINIT) and the variable ar is dereferenced without checking for null (thus FORWARD_NULL).
Probably this code will work:
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
int fn1(int **ar)
{
int *a = NULL;
if (ar == NULL) {
fprintf(stderr, "Omg! you passed NULL as first argument to fn1 function. What to do now? Break the program flow for sure - return or abort() or exit() !");
abort();
return EXIT_FAILURE;
}
a = *ar;
return EXIT_SUCCESS;
}
This helps easily:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
strct1
{
int a;
int b;
char c;
};
int fn1()
{
strct1 *pvarA = NULL;
strct1 varA;
MEMSET(&varA, 0, sizeof (strct1));
pvarA = &varA;
if (fn2(&pvarA) != 0) // derefering NULL pointer error.
{
return 1;
}
/* some code */
}
int fn2(strct1 **pvarA)
{
/* some code */
*pvarA = varA;
/* some code */
return 0;
}

Creating a gets function that returns a char* on return pressed using a getchar function

I had this problem for a while. I cannot create a gets(int maxChar) function that allows the user to get a char* using a get_char() function.
My current code:
char* gets(int maxChar) {
char a;
char* b;
int i;
for(i = 0; i<maxChar; i = i + 1){
a = getchar();
if (a != 0x0D) {putchar(a);} else {puts("\r\n");break;}
b[sizeof(b)] = a;
}
if (sizeof(b) > maxChar-1) {puts("\r\n");}
return b;
//if (b[sizeof(b)-1] != '')
}
the get_char() function works perfectly.
Full kernel.c: https://pastebin.com/3bqTbHsv
Change
char* b;
to
char* b = (char *)malloc(maxChar);
and
b[sizeof(b)] = a;
to
b[i] = a;
Also, change
if (sizeof(b) > maxChar-1) {puts("\r\n");}
to
if (i > maxChar-1) {puts("\r\n");}
The changes made are:
You have created a pointer, but have not allocated any memory. Hence the malloc statement.
sizeof(b) will always be 4 for a 32-bit compiler. You need the array index, given by i.
Same as 2.
These are the basic changes you need to make, without any change to your logic.
The following is an educated guess at what you were attempting to do. It includes some explanations, and a calling example:
char* _gets(int maxChar) // change name to avoid conflict with library 'gets'
{
//char a; //addresses concern pointed out in comments.
int a; //variable is used by function that can return EOF (-1)
int i=0; //
char* b = calloc(maxChar + 1, 1);//point pointer to memory (that it owns)
if(b) //test for success before going on
{
for(i = 0; i<maxChar-3; i = i + 1) // -3 to leave room for \r\n\0
{
a = getchar();
if ((a != 0x0D) && (a != EOF))
{
putchar(a);
b[i]=a;// place char into string accumulator
}
else break;// either EOF or <ENTER> occurred
} // no need for else in this implementation as we can handle
// the clean up once the conditions are met by outputting
// user's entries, then preparing your string (array) for return
puts("\r\n");
b[i++]='\r';
b[i++]='\n';
b[i++]='\0';
}
else return NULL;//failed to allocate memory. leave
return b; // return b (now a string)
//if (b[sizeof(b)-1] != '') // not sure what this was for
}
int main(void)
{
char *strArray = _gets(10);//creates memory for strArray
if(strArray) //use only if not NULL
{
printf("The array contains: %s", strArray );
free(strArray );
}
return 0;
}

qsort endless loop causes error C

So I´m stuck with this sort function because everything seems to work fine when I debug it and there are no errors or warnings what so ever but it somehow gets stuck in an infinite loop.
My struct(if it helps):
typedef struct raeume{
char number[5];
char klasse[6];
int tische;
}raeume;
my start of the qsort function:
void ausgabesortiert(struct raeume *arr[],int used,int size)
{
qsort(*arr,size,sizeof(raeume),cmp);
ausgabesortiert(arr,size,used);
}
my compare function:
int cmp(const void * a, const void * b)
{
raeume *raumA = (raeume *) a;
raeume *raumB = (raeume *) b;
int tempA = raumA->klasse[0] - '0';
int tempB = raumB->klasse[0] - '0';
if(tempA < tempB)
{
return -1;
}
else if(tempA > tempB)
{
return 1;
}
else if(tempA == tempB)
{
if(raumA->tische > raumB->tische)
{
return -1;
}
else if(raumA->tische < raumB->tische)
{
return 1;
}
else if(raumA->tische == raumB->tische)
{
return 0;
}
}
return 0;
}
The declaration of your ausgabesortiert function
void ausgabesortiert(struct raeume *arr[],int used,int size)
clearly suggests that array arr contains pointers to struct raeume objects, not the objects themselves.
But the call to qsort
qsort(*arr,size,sizeof(raeume),cmp);
and the comparison function are written as if you are trying to sort an array of struct raeume objects themselves that begins at arr[0] location.
While there's nothing formally invalid in this, it still looks rather strange. Is this really your intent? What exactly are you trying to sort, again? The arr array or some other array pointed by arr[0]? I suspect that it is the former, in which case you need to fix the qsort call and comparison function.

can't print values when call structure values from main function

i have decleard a structure and allocate some memory too . using a function i update datas . i got error segmentation fault when i acssing data.
This is my code
In headerfile :
typedef struct
{
int member;
char *name;
}place;
void update(place **,int);
void display(place **,int);
in function
static memallocate(place **ptr,int viname,int index)
{
ptr[index]=(place *)malloc(sizeof(place));
ptr[index]->name=(char *)malloc(viname*sizeof(char *));
}
void update(place **ptr,int index)
{
---read string value "na" find the strlen as "pp"---
memallocate(ptr,pp,index);
ptr[index]->name=na;
}
void display(place **ptr,int index)
{
int i;
for(i=0;i<index;i++)
{
printf("%s\n",ptr[i]->name);
printf("%s\n",ptr[i]->country);
}
}
in main file :
void main()
{
int index=0;
place *pla[5]={NULL};
while(index<2)
{
update(&pla[index],index);
index++;
}
display(pla,index);
}
my problem is i got segmentation fault when acessing function display and can't print datas ptr[0]->name,ptr[0]->country,ptr[1]->name,ptr[1]->country ..why this happen ? any memory fault . I got printing when i use printf after each updation .
I see two mayor issues here.
1st
Here
static void memallocate(place **ptr,int viname,int index)
{
ptr[index]=(place *)malloc(sizeof(place));
ptr[index]->name=(char *)malloc(viname*sizeof(char *));
}
you allocate too much memory. It shall be
static void memallocate(place ** ptr, int viname, int index)
{
ptr[index] = malloc(sizeof(place));
ptr[index]->name = malloc(viname * sizeof(char));
}
or even better:
static int memallocate(place ** ptr, size_t viname, size_t index)
{
int result = 0;
if (NULL == ptr)
{
result = -1;
errno = EINVAL;
}
else
{
ptr[index] = malloc(sizeof *ptr[index]);
if (NULL == ptr[index])
{
result = -1;
}
else
{
ptr[index]->name = malloc(viname * sizeof *(ptr[index]->name));
if (NULL == ptr[index]->name)
{
result = -1;
free(ptr[index]);
}
}
}
return result;
}
2nd
Then here (assuming na to be a char* properly initilaised to reference a C-"string")
void update(place **ptr,int index)
{
---read string value "na" find the strlen as "pp"---
memallocate(ptr,pp,index);
ptr[index]->name=na;
}
you overwrite what you just assigned to name. To copy a C-"string" use strcpy().
int update(place ** ptr, size_t index)
{
---read string value "na" find the strlen as "pp"---
int result = memallocate(ptr, pp, index)
if (-1 == result)
{
perror("memallocate() failed");
}
else
{
strcpy(ptr[index]->name, na);
}
return result;
}
Then call it like this:
int main(void)
{
size_t index = 0;
place * pla[5] = {NULL};
/* Loop over all array's elements. */
while (index < sizeof pla/sizeof *pla)
{
update(pla, index);
++index;
}
...
}
Notes:
Always check the outcome of relevant function calls (here malloc()) and design your functions to be able to pass failures up to the caller.
Do not cast the result of malloc(), calloc() and realloc() in C. It is not needed nor recommended.
Prefer using size_t over int for memory sizes and indexes. size_t does not waste a bit for negative numbers and it is guaranteed to be large enough to address any arrays' element or represent any memory size. sizeof as well as strlen() return size_t not int for example.
When you call your update(), you are passing a place ** of the current index as argument.
However, you nevertheless pass index too and later in your memallocate() allocate memory as if it was a pointer to the place *[].
So it should help to remove the parameter index from update() and memallocate() and change the memory allocation to something like:
*ptr = (place *)malloc(sizeof(place));
*ptr->name = (char *)malloc(viname*sizeof(char *));

How to get a function to return a string?

How do we return a string from a function?
I'm just beginning to learn to use the string functions and malloc, basically, i'm trying to get:
ef = 11101111
as an output.
Here's what i've tried.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
const int MAXWORD = 2;
char hexToBinary(char hex[MAXWORD]);
int main()
{
char hex[MAXWORD] = {'e','f'};
printf("%s = %s\n", hex, hexToBinary(hex));
return 0;
}
char hexToBinary(char hex[MAXWORD])
{
char *hexToBn = malloc( (MAXWORD-1) * sizeof(char) );
char *convertedString = malloc( (MAXWORD-1) * sizeof(char) );
for(int i=0 ; i<MAXWORD ; ++i)
{
if(hex[i] == 'e' || hex[i] == 'E')
{
strcpy(hexToBn, "1110");
}
if(hex[i] == 'f' || hex[i] == 'F')
{
strcpy(hexToBn, "1111");
}
strcat(convertedString, hexToBn);
}
return convertedString;
}
If you would like to make a function that returns a C string, declare it returning char*:
char *hexToBinary(char hex[MAXWORD]) {
...
}
This is not ideal, because it creates a possibility of a memory leak. In fact, your code would leak a string, because you never free what's allocated in malloc.
You should either fix the leak by capturing the return value and calling free once you are done with it, or use the buffer+length API pattern:
char *bin = hexToBinary(hex);
printf("%s = %s\n", hex, bin);
free(bin);
An alternative API would look like this:
void hexToBinary(char hex[], char bin[], int len) {
... // Users pass the output buffer bin and its length len
}
Couple ways to do so:
1: Allocate string on the heap and pass it to the caller. The caller ensures the string is delete using free.
char * get_str()
{
char * str = malloc(string_length + 1);
// Do something
return str;
}
2: pass the string to the function
void update_string(char * input, int length)
{
// modify string
}
Declare the return type as char*. Then use it like you would.
Note: you may have to do other things to your code. I just said the first thing I saw at a glance. Also, you need to make sure that your memory is deallocated with free when you are done with it.

Resources