3

I have following simple code:

#include <cstdio>
#include <queue>
#include <iostream>

struct Pacient {
int ill_state;
int ev_num;
bool operator==(const Pacient& other) const {
    return ill_state == other.ill_state && ev_num == other.ev_num;
}
bool operator<(const Pacient& other) const {
    return (ill_state < other.ill_state) || (ill_state == other.ill_state && ev_num > other.ev_num); // má menšiu prioritu, ak čaká kratšie (vyššie číslo na kartičke pri vstupe do ambulancie
}
bool operator>(const Pacient& other) const {
    return (ill_state > other.ill_state) || (ill_state == other.ill_state && ev_num < other.ev_num);
}
};

int main() {
char* ccmd;
std::priority_queue<Pacient> ps;
int ev_num, ill_state;
while (std::scanf("%s", ccmd)) {
    std::string cmd(ccmd);
    if (cmd == "dalsi") {
        if (ps.empty()) {
            std::printf("-1\n");
        } else {
            std::printf("%d\n", ps.top().ev_num);
            ps.pop();
        }
    } else if (cmd == "pacient") {
        std::scanf("%d%d\n", &ev_num, &ill_state);
        Pacient new_ps;
        new_ps.ev_num = ev_num;
        new_ps.ill_state = ill_state;
        ps.push(new_ps);
    } else if (cmd == "koniec") {
        break;
    }
}
return 0;
}

After compiling and entering something to stdin, I have got following segfault:

       Program received signal SIGSEGV, Segmentation fault.
__strlen_sse2_pminub () at ../sysdeps/x86_64/multiarch/strlen-sse2-pminub.S:38
38  ../sysdeps/x86_64/multiarch/strlen-sse2-pminub.S: No such file or directory.

I am using Ubuntu 13.10 64-bit. Could somebody please explain, what caused the problem?

Note: I am using scanf instead of cin, because I have specific instruction (from school) to use scanf, printf instead of cin, cout. I wouldn't use it otherwise.

4
  • scanf expects a char * when you use "%s". That said, use a std::string and operator>> or std::getline. Commented Feb 27, 2014 at 19:04
  • @Aashish Yes, I could, but I have specific instruction for this code to use scanf and printf. Commented Feb 27, 2014 at 19:07
  • @chris I am using it already. Commented Feb 27, 2014 at 19:07
  • Your title is completely off base: you are not reading into a std::string using scanf, you are attempting to read a char *, which is a c-style string. Commented Feb 27, 2014 at 19:09

3 Answers 3

2

Declare some storage for scanf to write into:

char ccmd[1000];

Otherwise, *ccmd is a random pointer with (probably) not enough storage for the characters to be written to. Note that scanf does not do indirection on that space.

Also, ccmd is already a pointer, so the extra & (address of) is not needed:

 std::scanf("%s", ccmd)
Sign up to request clarification or add additional context in comments.

5 Comments

To protect against stack overflow: std::scanf("%999s", ccmd)
@MaximYegorushkin: updated to address (somewhat more elegantly).
Are you sure that * allows you to specify the maximum field width? Also, field width for %s should not include space for \0, i.e. sizeof ccmd - 1.
@MaximYegorushkin: Oh, you are quite right. Retracted.
@wallyk I wish it did allow that though (.
0

You don't need to use std::scanf to read strings, you can use safe C++:

std::string cmd;
while(std::cin >> cmd) {
    // ...
}

5 Comments

I have specific instruction (from school) to use scanf and printf in this code.
@Benji this is rather strange that they ask you to use C++ and C-style input/output.
I heard it's because input to this program will be very large, and scanf should be faster than cin.
@Benji oh no, milliseconds wasted! Seriously, they should teach you proper idiomatic C++ code, then worry about performance.
@Benji Please note that scanf family of functions is prone to introduce stack overflows into your application, like scanf("%s") definitely does because you don't specify the maximum string length to read. In other words, scanf family of functions is harder to use correctly.
0

You did not initilaize pointer ccmd

char* ccmd;

and did not allocate memory where you are going to read a string

while (std::scanf("%s", &ccmd)) {

SO the program has undefined behaviour.

It is totally unclear why you do not want to use operator >> with stream std::cin and instead you use unsafe function scanf.

Also you need include header <string>. Otherwise if you will try to compile your program with other compilers you can get an error message.

And as pointed out @Maxim Yegorushkin even the call of function scanf is incorrrect. Instead of

std::scanf("%s", &ccmd)

There should be

std::scanf("%s", ccmd)

4 Comments

Please could you be more specific? E.g. exactly how to initialize that pointer?
@Benji It has to refer to allocated memory where you are going to read in a string. Now this pointer has some arbitrary value.
You pass char** into %s format, which is not correct.
But you can do sscanf("%ms", &ccmd) and it will allocate a buffer for you when using glibc. It is a non-standard extension.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.