0

I observed that in line int *x = malloc(sizeof(int)); this code is trying to convert a void* into a int* without using proper typecasting. So according to me answer should be option A. But in official GATE-2017 exam answer key, answer is given D. So am i wrong ? how ?

#include<stdio.h>
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>

int *assignval(int *x, int val){
  *x = val;
  return x;
}

void main(){
    clrscr();
    int *x = malloc(sizeof(int));
    if(NULL==x) return;
    x = assignval(x,0);
    if(x){
        x = (int *)malloc(sizeof(int));
        if(NULL==x) return;
        x = assignval(x,10);
    }
    printf("%d\n",*x);
    free(x);
    getch();
}
  • (A) compiler error as the return of malloc is not typecast appropriately.
  • (B) compiler error because the comparison should be made as x==NULL and not as shown.
  • (C) compiles successfully but execution may result in dangling pointer.
  • (D) compiles successfully but execution may result in memory leak.

In my opinion option D is only correct when int *x = (int *)malloc(sizeof(int)); is used.

mch
  • 9,424
  • 2
  • 28
  • 42
Prakhar
  • 52
  • 10
  • (1) Research about proper indentation. It's all the same for the compiler, but makes a great deal of difference to humans. (2) Why are you leaking the memory `x` points to by reallocating it? – StoryTeller - Unslander Monica Mar 15 '17 at 08:21
  • See http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc. to eliminate A. The answer is D, since you overwrite the pointer `x`. – Bathsheba Mar 15 '17 at 08:24
  • 2
    I also don't like `void main()`. A smart Alec would amend the exam question with this as option E. – Bathsheba Mar 15 '17 at 08:25
  • 2
    [Don't cast malloc](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc#605858). – Schwern Mar 15 '17 at 08:26
  • 5
    Your instructor either doesn't know C well, or this is a trick question. The `iostream.h` strongly implies a C++ compiler (an ancient compiler, in fact). which means option A is the only one that can possibly be correct. – StoryTeller - Unslander Monica Mar 15 '17 at 08:28
  • @StoryTeller Is the very smart answer ! – Bathsheba Mar 15 '17 at 08:32
  • 1
    In C language you are *supposed* to convert `void *` to `int *` *without* explicit cast. That the right way to do it. Unnecessary explict casts are extremely bad practice and shoud be avoided at all costs wherever possible. – AnT stands with Russia Mar 15 '17 at 08:36
  • ok i got it. I should not be using iostream and conio. And that casting with malloc is not necessary in C but in C++ its necessary. Also im compiling my code with c++ compiler instead of c compiler. Thank you all – Prakhar Mar 15 '17 at 08:38
  • @Prakhar: If you are compiling your code as C++, then why are you misleading people by tagging your question as [C]? – AnT stands with Russia Mar 15 '17 at 08:39
  • @AnT i didnt know it untill now. Thats the reason i asked for help here and got answer. Sorry for discomfort anyway. Im new to C and C++. – Prakhar Mar 15 '17 at 08:40

4 Answers4

6

There's no right answer among the choices offered.

The immediately obvious problems with the code, under assumption that the code is supposed to be written in standard C:

  • Standard library does not have <conio.h> header or <iostream.h> header.

  • void main() is illegal. Should be int main(). Even better int main(void)

  • clrscr(), getch() - standard library knows no such functions.

  • The second malloc leaks memory allocated by the first one (assuming the first one succeeds).

  • Result of second malloc is explicitly cast - bad and unnecessary practice.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • neglect conio.h, actually i was using an old ide (turbo c) – Prakhar Mar 15 '17 at 08:35
  • I got it answer is D which is right. Also standard library doesn't have iostream and conio header files. Memory leak will occur as we lose track of first assignment of memory to x. In C their is no need to manualy typecast malloc. – Prakhar Mar 15 '17 at 08:45
  • The `#include ` is a hint the code is (pre-standard) C++, not C. That and the various points you raise suggest the quality of the exam itself is VERY low. – Peter Mar 15 '17 at 09:45
0

The statement :

int *x = malloc(sizeof(int));

will not lead to compile error, as it declares x as a pointer to int and initializes it right afterwards. It did not have type void beforehand.

The statement :

x = (int *)malloc(sizeof(int));

causes a possible memory leak, as it reallocates the memory which is already allocated for x.


NOTE : However none of this answers is completely correct. This code will not compile for various reasons.

If this is your code, change :

void main()

to :

int main(void)

and also see why you should not cast the result of malloc.

Apart from that, clrscr(), getch(), <conio.h> and <iostream.h> are not recognized by standard library.

Community
  • 1
  • 1
Marievi
  • 4,951
  • 1
  • 16
  • 33
-1

I observed that in line int *x = malloc(sizeof(int)); this code is trying to convert a void* into a int* without using proper typecasting.

There's more than a little debate about whether or not to cast malloc, but it's a stylistic thing. void * is safely promoted to any other pointer.

ISO C 6.3.2.3 says...

A pointer to void may be converted to or from a pointer to any incomplete or object type. A pointer to any incomplete or object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.

Whatever you choose, pick one and stick with it.


The memory leak is here:

int *x = malloc(sizeof(int));
if(NULL==x) return;
x = assignval(x,0);
if(x){
    // Memory leak
    x = (int *)malloc(sizeof(int));

The first malloc points x at allocated memory. The second malloc can only happen if the first succeeded (if x is true). The pointer to the memory allocated by the first malloc is lost.

Using a new variable would fix the leak, keeping in mind that the code is nonsense.

int *x = malloc(sizeof(int));
if(NULL==x) return;
x = assignval(x,0);
if(x){
    int *y = malloc(sizeof(int));
    if(NULL==y) return;
    y = assignval(y,10);
    free(y);
}

As a side note, void main() is technically not a violation of the ISO C standard, it is "some other implementation-defined manner".

5.1.2.2.1 says:

The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:

int main(void) { /* ... */ }

or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared):

int main(int argc, char argv[]) { / ... */ }

or equivalent;) or in some other implementation-defined manner.

I'm guessing you're using a Windows compiler, that would be the "some other implementation". clang considers it an error.

test.c:8:1: error: 'main' must return 'int'
void main(){
^~~~
int
1 error generated.
Community
  • 1
  • 1
Schwern
  • 153,029
  • 25
  • 195
  • 336
-1

you should never forget that a void * pointer can be assigned to all type of pointers. in IDEs like visual studio, you get a compile error if you do not perform casting while assigning a void * to <>. for example:

float *ptr = malloc(sizeof(float));//compile error in visual studio.

but if you compile it with GCC without typecasting, you won't get a compile error.

Fatemeh Karimi
  • 914
  • 2
  • 16
  • 23
  • 2
    That's because the compiler with Visual Studio is a C++ compiler, in which implicit conversion from `void *` to another pointer is not permitted. In standard C, typecasting the return value from `malloc()` is permitted but is poor practice. – Peter Mar 15 '17 at 09:38
  • @Peter: Wrong. Compiler in Visual Studio is not a "C++ compiler". It is "whatever you configure it to be" compiler, which can properly compile C code and C++ code, exactly like GCC and most C/C++ compilers available today. Meanwhile, the above claim that the need to cast is somehow tied to "IDE" is completely nonsensical. – AnT stands with Russia Mar 15 '17 at 10:00