A fairy tale about social security in reverse

Do you remember your first interview? I remember mine very well, the teacher spent longer than usual running my pls in the Keil-C simulator, finding fault with every little thing, getting to the bottom of every comma in the firmware code. And then I started working on circuit board tracing algorithms, which we were supposed to take only in the next semester. I was already mentally preparing for the additional test, it’s clear that it’s going down, just like the previous two classmates. But at the end of the MK design lab, the teacher asked if I wanted to make “iron for the railway?” (With). For a second-year ITMO student who was supported by his parents and worked part-time unloading cars at night, this was akin to an offer on Google. Since then, I’ve been on both sides of the table many times, both as a test subject, as a picky lead (not at all proud of it, but not ashamed of it), and as a support group for colleagues in neighboring departments. I always wanted to hope that our interviews are not mysterious quests, where each task is a cast of a complex spell, and mistakes are not thrown out of the dungeon.

But first, a tale about how Misha came to us: once in the glorious city of S, a Jedi pogromist named Mikhail went for an interview at the Kodosaurs company. He was sure that he knew everything, and even studied the latest frameworks “NoScript” and “Unreal C–“. As he thought, nothing could stop him. When Misha came for an interview, he was met by an HR manager named Anna. She asked with a smile: “Tell me, how would you explain to your grandmother what a mutex is?” Yeah, right out of the gate, our valiant HR threw a seed question at Mishka. Well, what, this is a fairy tale, heroes on white scooters and all that…

Why did you choose our company?

Why did you choose our company?


So let our Anya fumble around in synchronization primitives. Mishka did not flap his ears, smiled and began to talk about asynchronous tasks, callbacks and atoms. Any grandmother would be proud of such a grandson, he thought. Then Mikhail was taken into the hut, Anechka fled to the kitchen to make coffee, unable to comprehend the information received. Oh, no – she went to finish writing a test task for beginners. However, it doesn’t matter, this is a fairy tale – our hero was taken around the office, shown serfs in the fields ruddy devops (damn, it turned out ugly) and were sent to a meeting room, where a little later the lead of the department, which our then young hero wanted to get into, came up. Not allowing anyone in the room to relax, he immediately gave out a standard riddle: “How do you turn a line backwards without using additional memory?”, and sat down opposite the candidate to write code in his taste book, casting an invisibility spell on himself so as not to interfere with Misha’s thinking . The invisibility spell did not pass the intelligence test, but the hero did not show it and tried to solve the problem in his head, because they also did not give a piece of paper. As a result, a whole carnival of symbols and indexes took place in his head, in the end, he came to a decision and declared it “In the corruption of words, start from baptism and move to the beginning, change the letters, in reverse order.” What was said was enough for the dungeon boss to teleport into the meeting room, i.e. those studio lead and started throwing fireballs at Misha, oh… asking slippery and tricky questions. Mishanya fought back as best he could, did not get confused in his answers, carried out a couple of attacks with lightsabers in moments of respite, and pressed the enemy with questions about the tech stack, the build farm, and the review process. Finally, the mana in the boss’s mug dropped to a critical level, and at the last sip, the lead of the Kodosaurs studio gave the task to rewrite the rocket control panel in NoScript. For the ritual they left a smack book, an hour of time and some kind of mother, calling on the spirits Gugol and Yara did not bring much success, but Annathea appeared twice and offered to drink living water, the water was really brown, and for some reason it smelled like coffee, which was not Nescafe, but Mishanya didn’t believe in fairies and drove the temptress away with questions about spinlocks, after which Annafeya melted away into a light haze.

The stars aligned, the code was mixed with riddles, the magic of ctrl+shift+B made it possible to see three cherished words: “Compiled without errors!” Mikhail emerged from the dungeon as a winner, increased his charisma level and increased his self-confidence skill. The boss, as usual, in annoying anger, muttered his final curse – “We will call you back in a week,” and did not call back. And it’s great, because then Mishanya wouldn’t have received an offer from Gaijin, where he began his adventure in the world of 3D engines that squeeze out 60 fps on dead hardware with hundreds of active objects on the stage and full-length industrial pluses. Sound familiar?

We will call you back!  Yeah, after the rain on the full moon

We will call you back! Yeah, after the rain on the full moon

Uff… about lightsabers was probably unnecessary. I only had the chance to go through Mishani’s fairytale path once, apparently because of my acquaintances. After some time, I began to conduct interviews myself, selecting people for the team. I never made secrets from our own questions; they somehow accumulated themselves in a text file and even hung for some time on the company’s website in the “Career” section and anyone could look at them. And it’s difficult to call them questions, but rather different interesting fragments of code that do not behave as expected, some are more complex, some are simpler.

At first, when participating in other interviews, I copied both the questions themselves and established patterns of behavior. But then it began to get boring, the point is to lean heavily on hardware or algorithms, if a person doesn’t fit into the team, there’s not much, if in a couple of months you have to look for a new one. But this is my couple of months, which I will spend on training, taking this time away from my tasks and team. I’m not saying that you shouldn’t ask about algorithms, on the contrary, you should. Let the person tell you which ones he knows and tell in detail about the couple of his choice. Having tried different interview formats, from fairy-tale ones, it’s good that there was a wise leader who, after the first such holiday, called to him and told him not to see such garbage again, so we skipped this step right away. Almost. Max, sorry, you were just unlucky, I was young and stupid. Then there were standard 10-15 questions on a sheet in the style of a blitz survey with a minute to think about it and a small test for an hour here and now.

Later, my team and I came up with a rather unusual selection process, let’s call it “social security in reverse” – it was after such social security that we got several excellent specialists into the department who would not have gotten to us otherwise. As it turned out later, one hated tests and simply left social security when he was offered to do them, while he has a great github (https://github.com/megai2/d912pxy) and the man single-handedly pulled off a pretty big pet project for 1k stars. The second one simply burned out at his previous job, became disillusioned with programming and stumbled on basic questions on the standard and stl, but opened up when it came to low-level optimizations at the ASMA level, or it was necessary to reverse the algorithm from ASMA and everything like that. They tried to place the main emphasis on those people whose knowledge was lacking in the team, even if it did not meet other criteria. I’m not saying that this is a panacea; social security is, in any case, a conversation between two parties who are trying to sell themselves to each other. As a representative of the company, I am selling the company to a person and there is no point in lying about the rocket control panel if, upon exiting the remote control, you only have to repaint the buttons and update the markings. Thank heavens, this is not about game development, there are a lot of interesting tasks here, just have time to sort them out.

Why, was that possible?

Why, was that possible?

On the part of a person who joins a company (it seems to me) there is also no particular point in exaggerating his ability to repair remote controls of different types, with pluses or flats, square or serpentine. Or brag about fixing the remote controls for Whensaurus and Robotonoid version 2.0. Anyway, we don’t know how to fix the square green remote control, or we know how, but we don’t know how yet, and we’ll have to read the documentation in the evening. As a representative of my loved one, I try to get more money and (less of a star in any form) the quality and quantity of tasks are interesting to me.

What is the idea of ​​“reverse social security”, the same list of questions, be it wrong, only we asked them to choose them at will and ask us, they answered the questions themselves, sometimes deliberately omitting some points, sometimes introducing inaccuracies, and our future colleague noticed or didn’t notice it. Added and corrected, or did not correct our stories, in most cases the person was drawn into the conversation.

At those interviews, I don’t remember us writing complex code, more often we didn’t write it at all, except for small explanations on paper. The very atmosphere of the interview as an exam was breaking down, and now the candidate was trying to catch us with the answers, asking questions not from the list, several times they could not calm us down for half an hour – the questions were pouring in one after another, we had to cast a taste book and a test. They paid attention to the person’s ability to clearly and distinctly express his thoughts, express an idea, ask a question, because the equipment can be improved, not now in a month or two. The skill in repairing rounded silver touchscreens will also develop over time, if a person is not particularly lazy. But the culture of the ability to conduct a conversation, exchange ideas and discuss technical issues in a review, without offending colleagues and without returning it 120 times for revision, is much more difficult to master (and most importantly, accept).

We get a TXT file that is very old

We get a TXT file that is very old

Actually, that’s all I wanted to tell you. And now the dancing, that is. questions. Some of the questions have already been raised here (https://habr.com/ru/articles/764514/ game from Fedya, I see many liked it), I hope these will be no worse, there may be duplicates. Some questions will seem simple to you, which means you write a lot of code and are generally a good person:

0x1…
Let me start with the classic question: what will be output as a result of the program?

void sayHello() {
    std::cout << "Hello, World!\n";
}
void sayНello() {
    std::cout << "Goodbye, World!\n";
}
int main() {
    sayНello();
    return 0;
}
And what is wrong?

But you need to compile, then “Goodbye, World!” will be displayed in the console. Because the second sayHello is written using Unicode, which unfortunately does not always work. And it is also called (clang, latest)

sayHello():                           # @sayHello()
        push    rbp
        mov     rbp, rsp
        mov     rdi, qword ptr [rip + std::cout@GOTPCREL]
        lea     rsi, [rip + .L.str]
        call    std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)@PLT
        pop     rbp
        ret
"_Z9sayНellov":                         # @"_Z9say\D0\9Dellov"
        push    rbp
        mov     rbp, rsp
        mov     rdi, qword ptr [rip + std::cout@GOTPCREL]
        lea     rsi, [rip + .L.str.1]
        call    std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)@PLT
        pop     rbp
        ret

0x2…
A this function has the amazing ability to alter reality depending on how many legs its caller has.

int abs_legs(int my_legs) {
  if (my_legs < 0) {
    return -my_legs;
  }
}
And what is wrong?

A function that returns a value must return a value (ahem!) from all possible branches, because there will always be a condition that will lead to undefined behavior. It seems this rule works not only for functions that return a value.

int abs_legs(int my_legs) {
  if (my_legs < 0) {
    return -my_legs;
  }
  return my_legs;
}

0x3…
This function is not fully revealed, leaving its magic behind the cover of the compiler. Where is the money, Zin?

int get_money(int index, const int *pockets) {
  int a = index + pockets[++index];
  // ...

  return a;
}
And what is wrong?

The compiler can rearrange the order of operation for index + pockets[++index], and this will lead to inconsistent behavior with different optimization settings. An unordered or undefined sequence of operations will cause a side effect when working with the index variable

int get_money(int index, const int *pockets) {
  ++index;
  int a = index + pockets[index];
  // ...
}

0x4…
What will be output to bufMatrix?

void umcp_read_buffer_from_pipe() {
  char bufKernel[12];
  char bufMatrix[12];
  std::cin.width(12);
  std::cin >> bufKernel;
  std::cin >> bufMatrix;
}
And what is wrong?

In this example, the first read will not overflow, and will fill the bufKernel with the truncated string. But the second reading may overflow bufMatrix, to prevent this from happening you must also call std::cin.width(12); before getting bufMatrix. Or use safe work via strings.

void umcp_read_buffer_from_pipe() {
  std::string bufKernel, bufMatrix;
  std::cin >> bufKernel >> bufMatrix;
}

0x5…
It seems that in this code the nil programmer is simply mixing randomness with absurdity and calling it “display customization”.

std::string str_func();
void display_string(const char *);

void set_display_options() {
  const char *str = str_func().c_str();
  display_string(str);
}
And what is wrong?

Here std::string::c_str() is called on a temporary std::string object. The resulting pointer will point to freed, but possibly still valid, memory after the std::string object is destroyed at the end of the assignment expression. Don’t rely too much on this though, it will lead to undefined behavior when accessing this pointer.

std::string str_func();
void display_string(const char *s);

void set_display_options() {
  std::string str = str_func();
  const char *cstr = str.c_str();
  display_string(cstr);
}

0x6…
How many times per evening will the bar be closed?

void ьщкт() {
  int *bar = new int;
  std::shared_ptr<int> p1(bar);
  std::shared_ptr<int> p2(bar);
}
And what is wrong?

Here, two unrelated smart pointers are created based on the same base value. When p2’s lifetime expires, it will delete the resource it controls. The p1 variable will not know about this and will try to delete this resource again, eventually deleting something. But that’s a completely different story.

void night() {
  std::shared_ptr<int> p1 = std::make_shared<int>();
  std::shared_ptr<int> p2(p1);
}

0x7…
Why is it dangerous to go to a bar in the morning?

void morning(const std::string &owner) {
  std::fstream bar(owner);
  if (!bar.is_open()) {
    // Handle error
    return;
  }

  bar << "customer";

  std::string str;
  bar >> str;
}
And what is wrong?

Because you might not get out. Data is appended to the end of the file and then read from the same file. However, since the pointer in the file remained in the same place at the end, trying to read data from the end of the file will result in UB. You should go to the bar in the evening, then everything “turns out great” (c).

void evening(const std::string &owner) {
  std::fstream bar(owner);
  if (!bar.is_open()) {
    // Handle error
    return;
  }

  bar << "customer";

  std::string str;
  bar.seekg(0, std::ios::beg);
  bar >> str;
}

0x8…
What one word needs to be changed for this code to work?

struct Foo {
  void *foo;
  struct foo *next;
};

static Foo foos;
static std::mutex m;
static std::condition_variable condition;

void consume_list_element(std::condition_variable &condition) {
  std::unique_lock<std::mutex> lk(m);

  if (foos.next == nullptr) {
    condition.wait(lk);
  }

  // Proceed when condition holds.
}
And what is wrong?

After the condition variable is released, we need to check if anyone took the element while we were switching the context.

  while (foos.next == nullptr) {
    condition.wait(lk);
  }

0x9…
Why does this rand() work like a random number generator from “Sony”? Here we need to explain a little about this meme; to generate rand() in its secret keys, Sony used a secret function that, due to an implementation error, returned the same number.

int main() {
  std::string id("ID");
  id += std::to_string(std::rand() % 10000);
  // ...
}
And what is wrong?

The number obtained by calling rand() is predictable and has limited randomness. To avoid repeating a generated sequence in some implementations of std::rand(), you must choose a generator that provides a truly non-repeating sequence. For example mtXXXX (https://dl.acm.org/doi/10.1145/272991.272995)

int main() {
  std::string id("ID");
  std::uniform_int_distribution<int> distribution(0, 10000);
  std::random_device rd;
  std::mt19937 engine(rd());
  id += std::to_string(distribution(engine));
  // ...
}

0xA…
Will the witcher receive coins?

class Witcher {
  int i;

public:
  virtual int TakeCoins(int l) { return i += 100; }
};

int main() {
  Witcher *geralt = new Witcher();

  memset(geralt, 0, sizeof(Witcher));

  std::cout << geralt->TakeCoins(100);
  return 0;
}
And what is wrong?

It is better not to use memset() to work with polymorphic types, it will destroy the pointer to vtbl in the class, such an object becomes invalid and an attempt to work with it will lead to UB

class Witcher {
  int i = 0;

public:
  virtual int TakeCoins(int l) { return i += 100; }
};

int main() {
  Witcher *geralt = new Witcher();

  std::cout << geralt->TakeCoins(100);
  return 0;
}

0xB…
Will the bard become a drunkard?

class Bard {
  int _beer;
  int _meal;

public:
  Bard(int meal) : _meal(meal), _beer(_meal - 1) {}
};
And what is wrong?

The member initialization list is broken and the _beer variable will be set first, and then the _meal variable will be initialized. Since the order of the variable declaration does not match what is declared in the class declaration, trying to read the value of _meal results in it having an undefined value. Most likely the bard will get drunk without a snack.

class Bard {
  int _beer;
  int _meal;

public:
  Bard(int beer) : _beer(beer), _meal(_beer + 1) {}
};

0xC…
In what case will a shot to the legs be especially effective?

for (auto format = begin(formats), __end = end(formats); format != __end; ++format) {
  if (snd::CodecNamesEq(....)) {
    format.is_stereo = true;
    formats.push_back(stereo_format);
  }
}
And what is wrong?

If formats is reallocated during the push_back() process, the format iterator will already point to remote memory, working with which will cause a bunch of problems.

0хD…
It’s better to try to assemble this code yourself to understand whether you are an admin? (https://onlinegdb.com/rMnPPq5et)

int main() {
    std::string access_level = "user";
    if (access_level.compare("user‮ ⁦// Check if admin⁩ ⁦")) {
        std::cout << "You are an admin.\n";
    }
    return 0;
}

0xE…
Sometimes in C++ it just wow and it works!

.∧_∧
( ・ω・。)つ━☆・*。
⊂  ノ    ・゜+.
しーJ   °。+ *´¨)
         .· ´¸.·*´¨) ¸.·*¨)
          (¸.·´ (¸.·'* ☆ Wizz, just works! ☆
But more often it takes a long time to debug

But more often it takes a long time to debug

0xF…
Not a single Mishan was harmed as a result of our social security services; Kostya answered all questions and added a couple of new ones to the list. Those who particularly distinguished themselves received an offer to join the team, but smart people moved on to the iOS/Android team. And Maxim then found himself in the backend team of the red bank.

This is the end of the fairy tale, and whoever finished reading, thank you for your attention.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *