pawel_j
pawel_j

Reputation: 429

Why the segfault on ostream std::string created from char array

this is something I cannot understand:

#include <iostream>
#include <fstream>
typedef struct point{
  char name[10];
  int y;
} point_t;


std::string print(const char* str, size_t size) {
  return std::string(str, size);
}

std::ostream& operator << (std::ostream &o,const point_t &a){
  o << print(a.name, sizeof(a.name)) << ", " << a.y;
}


int main(){
  point_t p = {
    {'0','1','2','3','4','5','6','7','8','9'},
    4
  };

  std::cout << "we have" << p << std::endl;
  return 0;
}

There is a segfault, which valgrinds shows on at

std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&) (in /usr/lib64/libstdc++.so.6.0.13)

which I cannot understand, because I can pring the string character by character and the segfault does not happen (for example << a.name[0] << a.name[1] << ... << a.name[9])

Any help appreciated.

Upvotes: 1

Views: 442

Answers (2)

Fred Larson
Fred Larson

Reputation: 62103

When I compile your code, I get this warning:

..\main.cpp: In function 'std::ostream& operator<<(std::ostream&, const point_t&)':
..\main.cpp:15:1: warning: no return statement in function returning non-void [-Wreturn-type]

This means you forgot to return the ostream in your stream insertion operator, causing undefined behavior. Fix it by adding the return:

std::ostream& operator << (std::ostream &o,const point_t &a){
  o << print(a.name, sizeof(a.name)) << ", " << a.y;
  return o;
}

I recommend always compiling with a high warning level and then striving for warning-free compiles. When the compiler is trying to help you, don't ignore it.

As @nvoigt noted, you should also #include <string>. Your standard library implementation might be getting that included from another header, but you shouldn't depend on that. Also, nothing you show here requires the #include <fstream>.

Upvotes: 2

nvoigt
nvoigt

Reputation: 77354

You code does not compile with my compiler (VS2017).

I fixed it to this:

#include <iostream>
#include <string>

typedef struct point {
    char name[10];
    int y;
} point_t;


std::string print(const char* str, size_t size) {
    return std::string(str, size);
}

std::ostream& operator << (std::ostream &o, const point_t &a) {
    o << print(a.name, sizeof(a.name)) << ", " << a.y;

    return o;
}


int main() {
    point_t p = {
        { '0','1','2','3','4','5','6','7','8','9' },
        4
    };

    std::cout << "we have" << p << std::endl;
    return 0;
}

Note the return statement for your operator and the include for string.

I don't have any problems with the fixed version. If your compiler did compile your version, I'd suggest you turn up the warning level or get a compiler that notifies you of errors.

Upvotes: 3

Related Questions