Solved

Another C Programming Puzzle

Posted on 2004-08-13
20
1,314 Views
Last Modified: 2007-12-19
void fun(void)
{
/*Do something here so that the main function prints something other than 20 */
}


void main()
{
             int i = 20;
             fun();
             printf("%d", i);
}

Question: What should be the contents of function fun() so that the printf in main prints something other than 20?
0
Comment
Question by:lemmeC
  • 10
  • 6
  • 3
  • +1
20 Comments
 
LVL 12

Expert Comment

by:andrewjb
ID: 11791120
Fiddle with the stack to change the 20 to something else. Is asm {} allowed? Not very portable..
0
 
LVL 5

Author Comment

by:lemmeC
ID: 11791134

>> Is asm {} allowed?
No clue. In fact, I do not know the solution.
For the moment, everything is allowed. :-)
 
0
 
LVL 12

Expert Comment

by:andrewjb
ID: 11791147
Platform specified?
0
 
LVL 5

Author Comment

by:lemmeC
ID: 11791162
Nope, nothing other than the question is specified.

I use Windows 2K on a Pentium with VC++ 6.0 and Turbo-C 2.01. Can also access a HP-UX on a Pentium with gcc on it.
I am looking for a solution which works on atleast one of these compilers.
0
 
LVL 12

Expert Comment

by:andrewjb
ID: 11791167
void fun(void)
{
  int x[1];
  x[3] = 20;
}

works on my compiler. If it doesn't on yours, try changing the x[3] to x[2] or x[4] or something.

.. and you'll probably need optimisations off.

0
 
LVL 5

Author Comment

by:lemmeC
ID: 11791225
Turbo C crashes with that code. Will try it out on VC and gcc.
0
 
LVL 12

Accepted Solution

by:
andrewjb earned 250 total points
ID: 11791251
Actually, you could probably try something like..

void fun(void)
{
  int x[1];

  int i;

  for ( i = -10 ; i < 10 ; i++ )
    if ( x[i] == 10 ) x[i] = 20;
}
0
 
LVL 5

Author Comment

by:lemmeC
ID: 11791671
Great. With some modifications, it worked on all 3 compilers (VC, Turbo C, gcc). Thanks!

Modified program:

void fun(void)
{
  int x[1];

  int i;

  for ( i = -50 ; i < 50 ; i++ )
    if ( x[i] == 20 ) x[i] = 10;  
}
0
 
LVL 12

Expert Comment

by:andrewjb
ID: 11791710
Ooops. Sorry. int i=20. I copied that to int i=10 which is why my last one was wrong :-)

Anyway, this isn't guaranteed to work at all. It's naughty, unportable and bad code.

Hope this is a puzzle, and not a real-world programming question!

0
 
LVL 5

Author Comment

by:lemmeC
ID: 11791804
Its just a puzzle, alright. Asked by my colleague as a challenge.
Anyways, thanks.
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Expert Comment

by:olsworld
ID: 11795091
good puzzle and amazing solution. i still wonder how the fun() is changing value of a variable declared in main ()... can any one of you pls throw some light on how it happens???

thanx a ton
0
 
LVL 5

Author Comment

by:lemmeC
ID: 11807024
olsworld,

>>can any one of you pls throw some light on how it happens?

The local variables of each function (including main) are kept in the function's activation record. The activation records reside in stack memory. In this case, the record for fun() would be adjacent to the record for main(). Andrew's solution searches for the variable i of main in the stack memory adjacent to the array variable x of fun and replaces i's contents with a new value.
Just goes to show how risky it is to use arrays without bounds checking.
0
 

Expert Comment

by:olsworld
ID: 11815578
i still wonder why it is not throwing memory leak error as it access the memory allocated to the program. and what if some other memory area also contains same value assigned to the variable declared in main().

is this solution guranteed to work on all platforms and all times? i doubt.
0
 
LVL 5

Author Comment

by:lemmeC
ID: 11817625
>> is this solution guranteed to work on all platforms and all times?
No, it isn't. As Andrew pointed out, its unportable and dangerous code, and should never be used in serious programs.
0
 

Expert Comment

by:olsworld
ID: 11843058
thanx a lot lemmeC for clearing my doubts.
0
 

Expert Comment

by:krkiran
ID: 11879671
Hi,

One possible solution is,

void fun(void)
{
  int j;
  *( (int*)((int*)(*(&j+1))-1) )=25;

  /*Explanation for the above statement
    (&j+1) - gives the EBP(Base Pointer) of fun()
    ( *(&j+1) ) - gives the EBP of main which is stored in fun() stack frame.
    ( (int*)(*(&j+1)) -1 ) - converting it into integer pointer and then decrementing it, to get the actual address of 'i' in main()'s stack frame
    *( (int*) ((int*)(*(&j+1))-1)  ) - Again converting it into integer pointer and changing the actual value of 'i' .
  */

}


void main()
{
           int i = 20;
           fun();
           printf("%d", i);
}

You can better use this code which tries to calculate the address of i in fun() and then changes its value. It is working with Linux, but not with Solaris. The stack frame generated by solaris might be different. lemmC, do you know how  stack frame is generated in solaris?

Thanks
Ravikiran
0
 
LVL 5

Author Comment

by:lemmeC
ID: 11879905
Ravikiran,
       Your code seems good, and your explanation is convincing. But it dumped core on HP-UX. I do not have a Linux system around right now. Will try it out when I get hold of one.

For the Solaris stack frame format, take a look at http://segfault.net/~scut/cpu/sparc/sparcstack/sparcstack.html.

0
 
LVL 5

Author Comment

by:lemmeC
ID: 11989394
Found a neat (and platform independent) way of doing it.

void fun(void)
{
#define printf(a,b) printf("10");
}

void main()
{
           int i = 20;
           fun();
           printf("%d", i);
}
0
 
LVL 12

Expert Comment

by:andrewjb
ID: 11989414
Excellent. Give the points (back) to that man!
0
 
LVL 5

Author Comment

by:lemmeC
ID: 11989421
No need. Your answer was great too! And I can't accept my own answer as a solution. :-)
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Character frequency paragraph 6 523
Determining Waypoint from series of waypoints and distances 10 172
Chinese Translation ---- Tshirt 12 360
is it possible in html5 7 326
What does UTC stand for?  “Coordinated Universal Time” – Think of this as the true time on Planet Earth that never changes with the exception of minor leap seconds here and there to account for the changes in the planet's rotation.   What does th…
We need a new way to communicate time sensitive or critical info.   The best part of my role at xMatters is visiting our clients all over the world to learn about how they operate their businesses, share insights that xMatters has gleaned across…
A company’s greatest vulnerability is their email. CEO fraud, ransomware and spear phishing attacks are the no1 threat to a company’s security. Cybercrime is responsible for the largest loss of money to companies today with losses projected to r…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

932 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now