C ++ глобальный указатель на символ? - PullRequest
0 голосов
/ 25 декабря 2011

Часть большой программы, которую я создаю, требует, чтобы путь был прочитан из командной строки и сохранен в классе. Поскольку пути могут быть произвольного размера и необходимы в нескольких функциях, я сохраняю их в char* в заголовочном файле. Но по какой-то причине, когда я присваиваю ему значение, программа segfaults.

Отладчик (gdb) показывает следующее:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b4828a in std::basic_istream<char, std::char_traits<char> >& std::operator>><char, std::char_traits<char> >(std::basic_istream<char, std::char_traits<char> >&, char*) ()
   from /usr/lib/libstdc++.so.6

Вот программа, которую я написал, чтобы продемонстрировать проблему:

test.cpp:

#include "test.h"

#include <iostream>
#include <cstring>

Test::Test() {
  filepath = NULL;
}

void Test::set_path(char* string) {
  char temp[strlen(string) + 1];
  strcpy(filepath, temp);
}

char * Test::get_path() {
  return filepath;
}

int main(int argc, char *argv[]) {
  std::cout << "Enter a file path: ";
  char *temp;
  std::cin >> temp;
  Test *temp2 = new Test();
  temp2->set_path(temp);
  std::cout << "Path: " << temp2->get_path() << std::endl;
}

test.h:

#ifndef TEST_H
#define TEST_H

class Test {
private:
  char *filepath;

public:
  Test();
  void set_path(char *);
  char * get_path();
};

#endif // TEST_H

Я не уверен, почему он падает. Что-то не так с методом, которым я занимаюсь? Кроме того, вместо того, чтобы просто переключиться на string s, я хотел бы узнать больше об этой проблеме.

Заранее спасибо!

Ответы [ 3 ]

3 голосов
/ 25 декабря 2011

temp (внутри main) неинициализирован и не указывает на какой-либо действительный выделенный блок памяти, поэтому строка:

std::cin >> temp;

вызывает ввод данных в неизвестную часть памяти, вызывая неопределенное поведение. Вы должны либо:

  • Сделать temp a char[] и читать только количество символов, которое поместится в буфере.
  • Укажите temp на допустимый буфер.
  • Еще лучше , сделать temp an std::string и позволить классу std::string беспокоиться об управлении памятью.


У вас также будет похожая проблема с filePath после того, как вы исправите вышеуказанную проблему. filePath устанавливается в NULL в конструкторе Test, а затем вы копируете temp в блок памяти, на который указывает filePath в Test::set_path:

strcpy(filepath, temp);

NULL относится к адресу, который вы не можете разыменовать. Вы должны изменить все ваши C-строки на std::string s и использовать функции-члены std::string и перегруженные операторы для работы со строками в C ++.

1 голос
/ 25 декабря 2011

Вы вызываете strcpy без выделения памяти для строки, которая будет скопирована в set_path. На странице руководства четко указано, что dest должно быть достаточно большим, чтобы содержать строку в src. К тому же ты копируешь с пустого временного. Хотя ваш сбой появляется рано, когда вы читаете из cin в неинициализированный указатель.

Использование std::string.

#include <iostream>

class Foo
{
public:
  Foo(const std::string& s) : s_(s) {} ;
private:
  std::string s_;
};

int main()
{
  std::string f;
  std::cin >> f;
  std::cout << f << std::endl;
  Foo foo = Foo(f);
  return 0;
}

Если вы действительно предпочитаете то, что делаете:

class Foo
{
public:
  Foo(const char* s) {
    size_t size = strlen(s);
    s_ = new char[size + 1];
    // safer
    strncpy(s_, s, size + 1);
  } ;
private:
  char* s_;
};

int main()
{
  char buffer[1024];
  // be save
  buffer[1023] = '\0';
  Foo foo = Foo(buffer);
  return 0;
}

Второй пример все еще не работает. Отсутствует правильный деструктор, конструктор копирования и оператор присваивания. Я оставлю это как упражнение.

0 голосов
/ 25 декабря 2011
Test::Test() {
  filepath = NULL;
}

void Test::set_path(char* string) {
  char temp[strlen(string) + 1];
  strcpy(filepath, temp);
}

Я не уверен, что вы думали, что strcpy собирался сделать, но он копирует из temp, который не инициализирован, в filepath, который равен NULL. Так что ни один из параметров не имеет никакого смысла.

...