0

I am writing a C++ program that takes in number from a file ("input10") of this format:

1    0    12
2    3    24
3    8    9
4    9    2
5    10   3
6    11   4
7    14   8
8    16   10
9    16   3
10   17   12

Each number goes into an array p_data[3] (three numbers to each line).

When running in Visual Studio, there is no error and the correct data is stored in the array. I include the #define _CRT_SECURE_NO_WARNINGS here so that I can use strncpy. I am not sure if strncpy is the source of the issue.

When running with g++ -std=c++11 on a CentOS terminal, I get the following error message:

Segmentation fault (core dumped)

I am finding this issue really difficult to debug. Any thoughts?

#include <iostream>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <fstream>
using namespace std;

void get_processes() {
    string curr_line;
    ifstream infile("input10");
    int p_data[3];
    int p = 0;
    char line[1024];

    while (getline(infile, curr_line)) {
        strncpy(line, curr_line.c_str(), sizeof(line));
        line[sizeof(curr_line) - 1] = 0;

        int p_data_count = 0;
        for (int i = 0; line[i] != '\0'; ++i) {
            if (line[i] != ' ') {
                string num = "";
                while (line[i] != ' ') {
                    num += line[i];
                    ++i;
                }

                if (p_data_count < 3) {
                    p_data[p_data_count] = stoi(num);
                    ++p_data_count;
                }
            }
        }
    }

    infile.close();
}

int main() {
    get_processes();

    return 0;
}
jshapy8
  • 1,983
  • 7
  • 30
  • 60
  • 1
    `sizeof(curr_line)` is wrong. That doesn't give the length of the string. I recommend [a good `std::string` reference](http://en.cppreference.com/w/cpp/string/basic_string). – Some programmer dude Oct 30 '16 at 07:00
  • 1
    And why use the array `line` to begin with? You can access each character of a `std::string` just like an array with the `[]` indexing operator. Or with iterators. Or with a range-based `for` loop. I think you need [a good beginners book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) to read. – Some programmer dude Oct 30 '16 at 07:01
  • Like I said, it works in VS. I'm primarily curious about why it's not working with g++. – jshapy8 Oct 30 '16 at 07:03
  • Are you saying that it's the *compiler* that crashes? Or the program when you run it? If it's the program, then run in a debugger to catch the crash in action, and see where in your code it happens. There's something called *undefined behavior* (UB) and if you have it it might work on one system but fail in another. – Some programmer dude Oct 30 '16 at 07:05
  • No, the program crashes when compiled with g++. – jshapy8 Oct 30 '16 at 07:12
  • 1
    By the way, can't you just use the normal input operator `>>` to read the numbers? Like in `while (infile >> p_data[0] >> p_data[1] >> p_data[2]) { /* do something with the numbers */ }` – Some programmer dude Oct 30 '16 at 07:28
  • That would also be a great way of doing it. – jshapy8 Oct 30 '16 at 07:37

1 Answers1

0

With C++ 11, we can just parse the string object as follows:

void get_processes() {
    string curr_line;
    ifstream infile("input10");
    int p_data[3];
    int p = 0;

    while (getline(infile, curr_line)) {
        int p_data_count = 0;

        for (int i = 0; i < curr_line.size(); ++i) {
            if (curr_line[i] != ' ') {
                string num = "";
                while (curr_line[i] != ' ' && curr_line[i] != '\0') {
                    num += curr_line[i];
                    ++i;
                }

                if (p_data_count < 3) {
                    p_data[p_data_count] = stoi(num);
                    ++p_data_count;
                }
            }
        }
    }

    infile.close();

}

Any C++ 11 compiler will recognize the stoi() method, and there is much less of a chance of a segmentation fault occurring.

jshapy8
  • 1,983
  • 7
  • 30
  • 60