safe malloc/realloc: wrapping the call into a macro? - c

I would like to wrap my calls to malloc/realloc into a macro that would stop the program if the method returns NULL
can I safely use the following macro?
#define SAFEMALLOC(SIZEOF) (malloc(SIZEOF) || (void*)(fprintf(stderr,"[%s:%d]Out of memory(%d bytes)\n",__FILE__,__LINE__,SIZEOF),exit(EXIT_FAILURE),0))
char* p=(char*)SAFEMALLOC(10);
it compiles, it works here with SAFEMALLOC(1UL) and SAFEMALLOC(-1UL) but is it a safe way to do this?

static void* safe_malloc(size_t n, unsigned long line)
{
void* p = malloc(n);
if (!p)
{
fprintf(stderr, "[%s:%ul]Out of memory(%ul bytes)\n",
__FILE__, line, (unsigned long)n);
exit(EXIT_FAILURE);
}
return p;
}
#define SAFEMALLOC(n) safe_malloc(n, __LINE__)

No, it's broken.
It seems to assume that the boolean or operator || returns its argument if it's deemed true, that's not how it works.
C's boolean operators always generate 1 or 0 as integers, they do not generate any of the input values.

Using your macro:
#define SAFEMALLOC(SIZEOF) (malloc(SIZEOF) || (void*)(fprintf(stderr,"[%s:%d]Out of memory(%d bytes)\n",__FILE__,__LINE__,SIZEOF),exit(EXIT_FAILURE),0))
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p = SAFEMALLOC(10);
char *q = SAFEMALLOC(2000);
printf("p = %p, q = %p\n", p, q);
// Leak!
return 0;
}
Warnings (should be a clue):
weird.c:8: warning: cast to pointer from integer of different size
weird.c:8: warning: initialization makes pointer from integer without a cast
weird.c:9: warning: cast to pointer from integer of different size
weird.c:9: warning: initialization makes pointer from integer without a cast
Output:
p = 0x1, q = 0x1
In summary, no, it's not very safe! Writing a function would probably be less error prone.

Related

Why I have error: deprecated conversion from string constant to 'char*' [-Wwrite-strings] in the line 5 and 6?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
char *preorden="GEAIBMCLDFKJH";//line 5
error in the above line
char *inorden="IABEGLDCFMKHJ";//line 6
error in this line
char *postorden;
error in this line
void post(char *pre, char *in, char *pos,int n)
{
int longIzqda;
if(n!=0){
pos[n-1]=pre[0];
longIzqda=strchr(in,pre[0])-in;
post (pre+1,in,pos,longIzqda);
post (pre+1+longIzqda,in+1+longIzqda,pos+longIzqda,n-1-longIzqda);
}
}
int main(int argc,char *argv[])
{
int aux;
aux=strlen(preorden);//convert to string
postorden=(char *)malloc(aux*sizeof(char));//use of malloc function
if (postorden){
printf("The preorden is: %s\n",preorden);
printf("The inorden is: %s\n",inorden);
post(preorden,inorden,postorden,aux);
postorden[aux]='\0';
printf("The postorden calculated is: %s\n",postorden);
free(postorden);
}
else{
fprintf(stderr,"Whithout memory\n");
return 1; // return 1
}
return 0;
}
the error is in the line 5 and 6
the compiler says:
deprecated conversion from string constant to 'char*' [-Wwrite-strings]
There are few issues with your code, firstly this
char *preorden="GEAIBMCLDFKJH";//line 5
forces compiler to warn you like below if compiled with -Wwrite-strings flags in C
deprecated conversion from string constant to 'char*'
[-Wwrite-strings]
because the string literal GEAIBMCLDFKJH stored in read only section of primary memory i.e pointer where it points, that contents is read only, hence instead of char* use const char*. for e.g
char *preorden = "GEAIBMCLDFKJH";/* preorden is normal pointer but "GEAIBMCLDFKJH" is read only, hence error */
And
const char *preorden = "GEAIBMCLDFKJH"; /* const char *ptr means ptr contents is read only */
Secondly, here
postorden=(char *)malloc(aux*sizeof(char));//use of malloc function
casting of malloc result is not required as malloc() return type is void* which is automatically and safely promoted to any other pointer type, Read Do I cast the result of malloc?. for e.g
postorden = malloc(aux * sizeof(*postorden));//use of malloc function
Also here(this point is about wrong comment on below line, please don't mind)
aux=strlen(preorden);//convert to string
strlen(preorden) returns the length of string pointed by preorden and gets assigned to aux not as written in comments(convert to string).
And change the post() definition to
void post(const char *pre, const char *in, char *pos,int n) {
/* some code*/
}
The message “deprecated conversion from string constant to 'char*' [-Wwrite-strings]” arises because the code was compiled as C++ code, which has different rules about string literals and pointer conversions from C.
This can be fixed by compiling the code as C code or worked around by inserting an explicit cast to char *.

typeof uses in C, besides macros

It's well known the use of typeof in Macros to make them type independent, such as container_of() and many other macros from the Linux kernel. It is unarguable that the typeof keyword unleashes a lot of power when used in these macros.
This question is about further use of the typeof keyword. What other contexts could the keyword bring lots of gain in C code, besides Macros?
One use of typeof is to const-cast a 2-dimensional array. In gcc, the construct:
extern void foo(const int a[2][2]); // or equivalently a[][2]
int a[2][2];
foo(a);
will generate:
"warning: passing argument 1 of 'foo' from incompatible pointer type".
(See http://c-faq.com/ansi/constmismatch.html for the reason why.) One way to fix this is to use a sledge-hammer-like cast, such as:
foo((void *)a);
Such a cast will happily take whatever you, perhaps mistakenly, give it.
But we can be much more delicate. By using the casting-macro CONST_CAST_2D given in the following code sample, the warning is eliminated. And more importantly, if you try to apply it to anything other than a 2-D array, you will get a compiler error/warning. CONST_CAST_PP works similarly, for a pointer-to-a-pointer.
#define CONST_CAST_2D(x) ((const typeof((x)[0][0])(*)[countof((x)[0])])(x))
#define CONST_CAST_PP(x) ((const typeof(**(x))**)(x))
#define countof(x) (sizeof(x) / sizeof 0[x]) // semi-standard define
static void foo(const int a[][2]) {} // takes const
static void bar(const int **b) {} // takes const
int main(void) {
int a[2][2]; // non-const
int **b; // non-const
foo(CONST_CAST_2D(a)); // ok
bar(CONST_CAST_PP(b)); // ok
return 0;
}
CONST_CAST_PP provides a clean and robust solution to a commonly-asked problem, e.g.:
Double pointer const-correctness warnings in C
c compiler warning when passing a char *arr[] to a function as const char **arr
What type is the reference to an array variable?
const cast and pointers to pointers
Why it's not safe to cast `char **` to `const char **`?
Why does implicit conversion from non-const to const not happen here?
Intel C++ Compiler warning 167 when non-const argument is passed as const parameter
And CONST_CAST_2D resolves:
How to eliminate warning for passing multidimensional array as const multidimensional array?
C function const multidimensional-array argument strange warning
A second usage of typeof is to generate pointers to constants, or pointers to function return values, as shown in the following example:
#include <stdio.h>
#include <time.h>
#include <sys/socket.h>
#define AMPERSAND(x) (&(typeof(x)){x})
int main(void) {
printf("%s\n", ctime(AMPERSAND(time(0)))); // pointer to time_t
setsockopt(0, SOL_SOCKET, SO_REUSEADDR, AMPERSAND(1), sizeof 1);
return 0;
}
This allows for straight-forward function composition, rather than having to save temporaries in named variables. (Unfortunately this doesn't extend to g++.)
Some people (myself included) dislike the syntax of the C++ const_cast<> operator, because;
It seems misnamed, because it removes const.
It seems to violate DRY, because it requires a redundant type arg.
But I am wrong: it is not misnamed, since it can also add const and/or volatile "cv" qualifiers, and it only partially violates DRY, since the compiler will catch any errors. So I dislike it slightly less and use it: it is safer than the C-style cast.
Using gcc's typeof, you can have almost the same type safety in C.
The following C code sample gives a CONST_CAST(T, x) macro, and illustrates its use:
#define REMOVE_QUALIFIER(cv, T, x) /* this macro evaluates its args only once */ \
__builtin_choose_expr(__builtin_types_compatible_p(typeof(x), cv T), ((T)(x)), \
(void)0)
#define ADD_QUALIFIER(cv, T, x) /* this macro evaluates its args only once */ \
__builtin_choose_expr(__builtin_types_compatible_p(typeof(x), T), ((cv T)(x)), \
(void)0)
#ifdef __GNUC__
#define CONST_CAST(T, x) REMOVE_QUALIFIER(const, T, x) // "misnamed"
#else
#define CONST_CAST(T, x) ((T)(x)) // fallback to standard C cast
#endif
void foo(void);
void foo(void) {
const int *a = 0;
const float *x = 0;
int *b = a; // warning
int *c = (int *)a; // no warning, unsafe standard cast
int *d = (int *)x; // no warning, and likely wrong
int *e = CONST_CAST(int *, a); // ok
int *f = CONST_CAST(int *, x); // error
unsigned *g = CONST_CAST(unsigned *, a); // error
const int **h = &b; // warning
const int **i = ADD_QUALIFIER(const, int **, &b); // ok
const int **j = ADD_QUALIFIER(const, int **, &x); // error
}
This technique can also be used to change the signedness of a type, reminiscent of C++'s std::make_signed and std::make_unsigned, or Boost traits. For example:
#define MAKE_UNSIGNED(T, x) ADD_QUALIFIER(unsigned, T, x) // T usually char*
This use of gcc's typeof is yet another reinterpret cast, using union-punning.
It can be applied to scalars and structures, as well as to pointers. It gives only an R-value.
#ifdef __GNUC__
#define PUN_CAST(T, x) (((union {typeof(x) src; T dst;})(x)).dst)
#else
#define PUN_CAST(T, x) (*(T*)&(x)) //<-- classic pun: breaks strict aliasing rules
#endif
Caveat: you can use this to cast a pointer into an array of 4 or 8 bytes, or vice versa. But you can't use it to cast a pointer into another pointer, in an attempt to avoid the strict aliasing rules.

why first code give error and second does not?

This is the first code:
#include <stdio.h>
#include <stdlib.h>
void test(int,int);
int main()
{
int p=23,f=24;
test(&p,&f);
printf("%d %d\n",p,f);
return 0;
}
void test(int q,int g)
{
q=q+q;
g=g+g;
}
This code generates TYPE MISMATCH ERROR maybe due to the fact that I have passed address of variable as argument during function calling and the formal parameters are not pointers.
This is the second code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int p=23,f=24,q,g;
q=&p;
g=&f;
printf("%d %d\n",q,g);
return 0;
}
The output of second code is
1638220 1638228
In this code, q and g are not pointers. So why are they giving correct output, not the error?
Note:
Your comment: "The second code prints the correct addresses of p and f where as first code gives error" is wrong on various levels.
You claim your printf statement prints the memory addresses of the variables? Wrong, it does no such thing. Can't. Impossible. Not going to happen.
To print the memory addresses of variables, a printf statement should look like this:
printf("p # %p\nf # %p\n", (void *) &p, (void *) &f);//one of few cases where you SHOULD cast
You're printing just a number:
printf("%d %d", p, f);
Those are not the same thing. Just take a look at the example at the bottom of this answer, but read the bit in the middle, too
Well, you declared q and g as ints, and assigned them the memory addresses of p and f. It's undefined behaviour (ie the standard doesn't determine what to do with this, so it may vary depending on the compiler, WCS: your application crashes). In your case, I'd say this happens:
Basically, a memory address looks something like this:
0x213ABC
A hexadecimal value, which can be interpreted as a number, so there's nothing stopping your from assigning it to a char, or size_t or whatever.
HOWEVER, if you compile your code with -Wall, you should get a warning about the implicit conversion from type int * to int. Aside from that, you're "safe". Mind your: the program's output will be unpredictable and therefore rather pointless.
The first snippet contains a bigger problem: you're passing a value to a function that simply does not exist! The test function cannot handle what you're passing, because its prototype shows it expects 2 ints, not 2 pointers
test(&p,&f);
//to:
test((int) &p,(int) &f);
However, it does compile, as you can see here, however the results are unpredictable (undefined behaviour).
When calling test(&p, &f) you are calling a function that should look like this:
void test(int *, int *)
However, this signature/prototype is nowhere to be found, so the compiler can't continue. Casting the memory addresses to ints changes all that, and lets the compiler know that the function looks like void test (int, int), and that function does exist, hence it compiles.
Think of it like this:
You: What's your phone-number?
Me: abc
you: That's not a phone number
Me: I meant 1-11-111 (number keys for text messages, those were the days)
That's what you're doing here:
test(&p, &f);
//compiler: can't find function test(int *, int *)
//you: I expect you to call test(int, int), and implicitly cast the pointers to ints
That's not how C works.
Note:
As pointed out to me in the coments: Assigning/casting pointer to int is undefined behaviour (ie: the result of these actions are not defined by the standard)
The example program that prints pointers, and unsigned long and ints as they should be printed:
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
int p = 2, f = 4, q;
q = (int) &f;
printf("p # %p\nf # %p\n", (void *) &p, (void *) &f);
//int is too small for 64bit address, use unsigned long here
printf("%d != %ul != %p\n", q, &f, (void *) &f);
return EXIT_SUCCESS;
}
When I ran it through this codepad, I got the following output:
p # 0xbf70e1d8
f # 0xbf70e1d4
-1083121196 != 3211846100l != 0xbf70e1d4

C Function returning an Array

I always thought that when you want to return an array from a function, the only way to do that was using pointers like so:
char * func();
But yesterday, while I was going through K & R, I noticed wrongly assumed that char x()[] is also a valid construct. So I went ahead to test this out and wrote up the following code:
#include <stdio.h>
#include <stdlib.h>
char string1[10] = "123456789";
char x(void)[10];
int main(void) {
printf("string returned by x() is %s",x());
return EXIT_SUCCESS;
}
char x(void)[10] {
return x;
}
Compiling using GCC on Windows, this threw the following errors:
..\src\07arrreturn.c:7:6: error: 'x' declared as function returning an array
..\src\07arrreturn.c: In function 'main':
..\src\07arrreturn.c:10:2: warning: format '%s' expects argument of type 'char *', but argument 2 has type 'int' [-Wformat]
..\src\07arrreturn.c: At top level:
..\src\07arrreturn.c:14:6: error: 'x' declared as function returning an array
..\src\07arrreturn.c: In function 'x':
..\src\07arrreturn.c:15:2: warning: return makes integer from pointer without a cast [enabled by default]
What is happening? am I mis-understanding what the book says? How can you return more than one value (or address) from a function? Isn't that restricted by the fact that you only have a single limited size CPU register that can hold the return value? If you have to return a big chunk of data, you can do so only by returning the address to it right?
Whats the deal with char x()[]? Is such a thing even used?
EDIT: I DID in fact misread the stuff from K&R. See comment below.
char x()[] is also a valid construct
Not as-is, and not quite in this context.
You can use similar syntax to:
declare a pointer to array: char (*arrPtr)[20];
declare an array of function pointers: void (*foo[20])(void);
dereference the return value (pointer) of a function call: char *foo(); char c = foo()[0];
declare a function that returns a pointer to array: char (*foo())[20]
or the same thing with a function pointer: char (*(*foo)())[20]
Which one of these are you looking for?
The C standard (ISO/IEC 9899:2011) says unequivocally:
6.7.6.3 Function declarators (including prototypes)
Constraints
1 A function declarator shall not specify a return type that is a function type or an array
type.
Thus your code is invalid.
K&R C is quite old. In ANSI C (C89), functions returning arrays aren't allowed and what you see is the result of this. First, you get errors for the declaration of x() as a function returning an array and due to this error, x() is never correctly declared and thereby treated like a function returning an int (because this used to be the default return type). This returned int is then supposed to be interpreted as char * generating the final warning.
If you need to return an array, you can wrap it in a struct. Otherwise return a pointer (make sure that the memory it points to is valid after returning).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char string1[10] = "123456789";
struct ret_s {
char string1[10];
};
struct ret_s x(void);
int main(void) {
struct ret_s r = x();
printf("string returned by x() is %s\n", r.string1);
return EXIT_SUCCESS;
}
struct ret_s x(void) {
struct ret_s r;
strcpy(r.string1, string1);
return r;
}

Double pointer conversions, passing into function with `const void **ptr` parameter

GCC gives me folowing warning:
note: expected 'const void **' but argument is of type 'const struct auth **
Is there any case, where it could cause problems?
Bigger snippet is
struct auth *current;
gl_list_iterator_next(&it, &current, NULL);
Function just stores in current some void * pointer.
The error message is clear enough: you are passing a struct auth ** where a void ** was accepted. There is no implicit conversion between these types as a void* may not have the same size and alignment as other pointer types.
The solution is to use an intermediate void*:
void *current_void;
struct auth *current;
gl_list_iterator_next(&it, &current_void, NULL);
current = current_void;
EDIT: to address the comments below, here's an example of why this is necessary. Suppose you're on a platform where sizeof(struct auth*) == sizeof(short) == 2, while sizeof(void*) == sizeof(long) == 4; that's allowed by the C standard and platforms with varying pointer sizes actually exist. Then the OP's code would be similar to doing
short current;
long *p = (long *)(&current); // cast added, similar to casting to void**
// now call a function that does writes to *p, as in
*p = 0xDEADBEEF; // undefined behavior!
However, this program too can be made to work by introducing an intermediate long (although the result may only be meaningful when the long's value is small enough to store in a short).
Hm... I think constructs like const void * doesn't makes much sense.
Because if user wants to access data under void * he needs casting from void, and this action bypasses compiler type checks and consequently - constantness.
Consider this example:
#include <stdio.h>
#include <stdlib.h>
int main () {
int i = 6;
int * pi = &i;
const void * pcv = pi;
const int * pci = pi;
// casting avoids type checker, so constantness is irrelevant here
*(int *)pcv = 7;
// here we don't need casting, and thus compiler is able to guard read-only data
*pci = 7;
return 0;
}
So conclusion is that we need either void pointer Or to ensure constantness of data, but not both.

Resources