【问题标题】:C++ global char pointer?C++ 全局字符指针?
【发布时间】:2011-12-25 03:31:10
【问题描述】:

我正在制作的较大程序的一部分需要从命令行读取路径并存储在类中。因为路径可以是任意大小并且在多个函数中都需要它,所以我将它存储在头文件中的 char* 中。但是,由于某种原因,当我为其赋值时,程序会出现段错误。

调试器 (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

我不确定它为什么会崩溃。我这样做的方法有问题吗?另外,我不只是切换到strings,还想了解更多关于这个问题的信息。

提前致谢!

【问题讨论】:

  • "而不是仅仅切换到strings,我想了解更多关于这个问题的信息。"为什么,你对strings 过敏?
  • 我确实最终使用了std::string'。我只是想弄清楚为什么char * 不起作用。

标签: c++ pointers char global


【解决方案1】:

temp(在main 内)未初始化且未指向任何有效分配的内存块,因此该行:

std::cin >> temp;

导致输入被写入内存的某个未知部分,从而导致未定义的行为。您应该:

  • temp 设为char[] 并仅读取缓冲区中可以容纳的字符数。
  • temp 指向一个有效的缓冲区。
  • 更好,将temp 设为std::string,并让std::string 类担心内存管理。


解决上述问题后,filePath 也会遇到类似问题。 filePathTest 构造函数中被设置为NULL,然后您将temp 复制到filePathTest::set_path 中指向的内存块:

strcpy(filepath, temp);

NULL 指的是不允许取消引用的地址。您应该将所有 C 字符串更改为 std::strings 并使用 std::string 成员函数和重载运算符来处理 C++ 中的字符串。

【讨论】:

  • 所以解决方案是将char 设为固定大小(如FILENAME_MAX)或使用std::string
  • @ChenXiao-Long:在 C++ 中,std::string.
  • 好的,我将使用std::string。谢谢你的回答!
【解决方案2】:

您调用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;
}

第二个例子还是坏了。它缺少适当的析构函数、复制构造函数和赋值运算符。我将把它留作练习。

【讨论】:

  • 感谢您的回答!我可能会坚持使用std::string,但我一定会看看你的第二种方法作为练习。
【解决方案3】:
Test::Test() {
  filepath = NULL;
}

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

我不确定您认为strcpy 会做什么,但它所做的是将未初始化的temp 复制到为NULL 的filepath。所以这两个参数都没有任何意义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-10
    • 2021-09-06
    相关资源
    最近更新 更多