Bloomberg LP Interview Question


Country: United States
Interview Type: In-Person




Comment hidden because of low score. Click to expand.
10
of 12 vote

I noticed the following issues:

1. No break statement used. So the value in buf will get over-written by case statements below 2. How to fix: use break after each case.

2. In default case, strncpy will copy 7 characters (i.e. strlen("Default")) into buf without leaving any space for '\0'. This might create issues later if any string function is used on buf. How to fix: allocate more memory.

3. buf, being a local variable in the function, will be allocated memory in the stack. After the function returns, the contents of the stack associated with this function will be popped and buf would be referring to an address which is not valid anymore. How to fix: allocate memory for buf using either malloc or new and return this address (as shown below):

char* buf = (char*) malloc (8 * sizeof(char)); return buf;

4. The word 'default' is spelt incorrectly :D

- Jester December 29, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

for 3.
eugene.yarovoi's solution is the right answer.
if u allocate memory inside the function, u need someone
reclaim them later,that is not what the interview want

- Anonymous December 30, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

"eugene.yarovoi's solution is the right answer."

Someone actually did bring up a legitimate objection to my answer (namely, that the signature ought to be changed to return const char* if one implements my solution). It might still be the best way to go on this question, though (see the comments to my answer).

- eugene.yarovoi January 04, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

then how about memory leak in this case. because we allocate the memory in the function, but who is getting free it

- rs February 11, 2012 | Flag
Comment hidden because of low score. Click to expand.
4
of 4 vote

char * test(int v)
{
switch(v)
{
case 1: return "Case 1";
case 2: return "Case 2";
case 3: return "Case 3";
default: return "Default";
}
}

- eugene.yarovoi December 29, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

That technically does make those strings implicit global variables, but I think this is probably what your interviewer wanted.

- eugene.yarovoi December 29, 2011 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

yeah so thats obviously not the answer as the type of a literal string is char const * not char *
although i gotta tell you gcc -Wall didn't even mention it. Which means if you modified one character of the returned string (which the type suggests one can do) then it would compile (gcc 4.6.2) with no warnings and will segfault at runtime.

The other candidate solution i saw here is mallocing which will obviously leak.

The only sane solution is switching to a fully functional lazy language like Haskell and forget all about this garbage.

- ex January 04, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I still stand by my earlier statement that my solution is likely to be what the interviewer was looking for. I wouldn't say it's "obviously not the answer".

Your point is valid though -- if this approach is to be used, this function should really be returning a const char*, lest the user inadvertently modify the values. The documentation (if it were to exist) can help here, of course.

"The only sane solution is switching to a fully functional lazy language like Haskell and forget all about this garbage."

I would say that is the least sane solution. So if you're working on a C codebase, you would switch to Haskell just because you're annoyed not all types are immutable in C? Simple problems merit simple solutions.

- eugene.yarovoi January 04, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

"you would switch to Haskell just because you're annoyed not all types are immutable in C?"

ad hominem much?

first i would explain the interviewers why the expected answers are all wrong.
then i would explain them how these problems don't ever arise in a functional language.
i'd go on to describe the gajillion advantages of functional languages (massive code reuse, referential transparency, safety, piece-of-cake concurrency and much MUCH more)
finally i would debunk their rebuttal that functional languages are inefficient and would call them morons for not doing their homework.

then i'd be kicked out of the building. oh well

- ex January 05, 2012 | Flag
Comment hidden because of low score. Click to expand.
2
of 2 vote

"case deafult:" should read as "default:" (spelling + no case)
Plus extra '('s in case 2 & 3 & default.

- Selmeczy, Péter December 29, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

you can use extern or define the array allocated at runtime as pointer and return the address....

- Sanjay Kumar December 28, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

define the array allocated at runtime? how is that done?

- BBemp December 28, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

use malloc

- Sanjay Kumar December 29, 2011 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

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

char * test(int v)
{
char *buf;
buf=(char *)malloc(7);
memset(buf,' ',6);
switch(v)
{
case 1:
strncpy(buf, "Case 1", strlen(buf));
break;
case 2:
strncpy(buf,"Case 2", strlen(buf));
break;
case 3:
strncpy(buf, "Case 3", strlen(buf));
break;
default:
strncpy(buf, "defult", strlen(buf));
}
return buf;
}
int main()
{
char *p = test(2);
printf("%s",p);
getch();
}

- Sanjay Kumar December 29, 2011 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

two options for this question. One is to use string literals and other one is to allocate memory dynamically using malloc.

- srik545 January 02, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

another error is that,
you should just return buf (not &buf), as buf is a pointer to the begin of array buf.
Answer to your question is to allocate memory rather than defining an array. as mentioned above.

- abhishekatuw December 29, 2011 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

You can use naked function to achieve the dynamic stack allocation.
Just leave ebp alone, and change ESP to what you want.
Although you can sub ESP to allocate memory in general speaking, but beware of the direction of stack growth. In some operating system, the direction is opposite.

- iambigasp January 07, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Just 2 bugs:-

1. There's nothing like case default ... Its just default
2. char buf[] is an array ... when we refer to buf, it means an address ... We cannot return an address of an address ... So instead of return &buf ... We should have return return buf

# include <iostream.h>

char * test(int v) 
{
char buf[6+1];
switch(v) 
{
case 1: strncpy(buf, "Case 1", sizeof(buf));
case 2: strncpy(buf,"Case 2", sizeof(buf)); 
case 3: strncpy(buf, "Case 3", sizeof(buf)); 
default: strncpy(buf, "Default", sizeof(buf)); 
}
return buf; 
}

int main() 
{
char * p = test(2);
cout<<p<<endl;
return 0;
}

- Mandar January 12, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

you can pass the array pointer to the function instead of returning it,
test(int v,char* buf);
char* buf=new char[7];
test(2,buf);

- Ayat.Rashad January 21, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

I know the Bloomberg guys. They don't care about wrong style of programming. They want to know what EXACTLY happens when you compile/run the program.

In this program there are two compilation errors:
1. case default
2. return &buf

If you fix these errors, what happens in the run-time?

case2, case 3, default -- will be all executed, as no break statements.
Each time different string copied into buf, but each time buf length is not exceeded, so its OK.

After the function returns, buf is deleted from the stack, as it was a local variable. Pointer p will point to some location in the stack (where previously resided buf).

Now operator cout will try to access (read) memory pointed by p.
cout 'thinks' p is char*, so it will try reading *p, *(p+1), etc. until it reaches null character.

So let's think: what resides in the stack where p points?

Before call to test the stack looks like:

ptr to char* p
----BOTTOM OF STACK ----

inside 'test' the stack looks like:

buf [7]
int param
return ptr of 'test'
ptr to char* p
----BOTTOM OF STACK ----

after 'test' returns, p will point on top of the stack (where previously resided buf[7]).
now at this location will reside ptr p itself!

So p will point on itself. The operator cout << will try to read null-terminated string from p.
So it will access *p, *(p+1), *(p+2), ... until it reaches byte with value zero.

As the stack in our case is really small: it contains only pointer p (which is 4 bytes), and this pointer probably does not contain any zero bytes, then segmentation fault will occur, because cout << will try to read memory beyond the bottom of the stack and the process will crash.

(In kernel mode, the process would probably not crash, but continue reading bytes untill zero byte reached).

- Leo March 08, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

#include <iostream>
#include<cstring>


using namespace std;
char buf[7];
char * test(int v)
{

switch(v)
{
case 1: strcpy(buf, "Case 1");break;
case 2: strcpy(buf,"Case 2"); break;
case 3: strcpy(buf, "Case 3");break;
default: strcpy(buf, "Default");
}
return buf;
}

int main()
{

char * p = test(2);
cout << p << endl;
return 0;
}

- viki410 July 28, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

The answer about the stack is the closest, however the conclusion is wrong. *p is going to point to the right string, however it is destroeyd when calling any function, like <<. So we should first save it and then call <<:
char * test(int v)
{
char buf[6 + 1 +1];
switch (v)
{
case 1: strncpy(buf, "Case 1", sizeof(buf));
case 2: strncpy(buf, "Case 2", sizeof(buf));
case 3: strncpy(buf, "Case 3", sizeof(buf));
default: strncpy(buf, "Default", sizeof(buf));
}
return buf;
}
int main()
{
char * p = test(2);
char tmpCopy[10];
for (int i = 0; i < 8; i++)
tmpCopy[i] = p[i];
cout << tmpCopy << endl;
return 0;
}

- all wrong answers March 04, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

char* buf2 = new char[7];
strcpy(buf2, buf);
return buf2;

- Anonymous December 29, 2011 | Flag Reply


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More