segmentation fault when using double brackets with printf

626 views Asked by At
#include<stdio.h>
#define POOLNAME_FMT "Hello"

void main() {

 printf((POOLNAME_FMT "Cannot allocate %d bytes" POOLNAME_FMT "in pool not enough memory",5));

}

Why does it give segmentation fault when I use double brackets with printf. i.e. printf(( ));?

3

There are 3 answers

0
Shahbaz On

Because (a, b) is actually a single value. It calculates a and b and returns the value of b.

So what you are doing is basically:

/* calculate before `,` and ignore */
POOLNAME_FMT "Cannot allocate %d bytes" POOLNAME_FMT "in pool not enough memory";
/* call printf with after `,` */
printf(5);

Which is clearly wrong.


When you write func(a, b) as a function call, C knows to send a and b as separate arguments to func. When you say func((a, b)), you are explicitely saying (a, b) is one value and that the result (i.e., the value of b) should be sent to func as a single argument.

If you compile with warnings, and if your compiler is nice to you, it could warn you about this. If your compiler is not nice, it should still complain that you are giving an int where a const char * is expected.

If using gcc, I highly recommend compiling with -Wall, always.

3
Shafik Yaghmour On

You are using the comma operator without realizing it:

( ... "in pool not enough memory",5)
                                 ^

since the comma operator will evaluate its left operand and discard the result and then evaluate and return the right operand, you end up with:

printf( 5 ) ;

which will attempt to convert an int to a const char *restrict for the format string, which will almost surely not point to valid memory. Without the (), the , would have just been a separator for the function arguments.

The () is an expression in this context; if we look at the C99 draft standard section 6.5.1 Primary expressions, we have:

( expression )

therefore the , is treated as an operator while we can see from section 6.5.2 Postfix operators:

postfix-expression ( argument-expression-listopt )
argument-expression-list:
   assignment-expression
   argument-expression-list , assignment-expression
                            ^

The , is just a separator in a function call.

Having warnings enabled should have helped here, gcc gives me a few warnings for this program:

warning: left-hand operand of comma expression has no effect [-Wunused-value]

and

warning: passing argument 1 of 'printf' makes pointer from integer without a cast [enabled by default]     note: expected 'const char * restrict' but argument is of type 'int'

0
mirabilos On

This is because printf is a function, which will accept its arguments in single parenthesës, and the second set of parenthesēs is actually opening up a subexpression:

(string "string" string "string" , 5)

The first four strings are concatenated at compile time, yielding:

("string", 5)

This is then evaluated:

  • "string" evaluates to a pointer to the first character of it
  • a,b evaluates a first, then throws the result away, then evaluates and returns b
  • 5 evaluates to an integer constant 5

So in effect, you're calling:

printf(5);

(This is because the string has no side effects.)

Something like this, however, would work:

printf((POOLNAME_FMT "Cannot allocate %d bytes" POOLNAME_FMT "in pool not enough memory"),5);

Note how the comma and the five were moved to outside of the parenthesised subexpression.