C++全局字符指针?

发布于 2024-12-22 16:45:41 字数 1349 浏览 1 评论 0原文

我正在制作的较大程序的一部分需要从命令行读取路径并将其存储在类中。由于路径可以是任意大小并且在多个函数中都需要它,因此我将其存储在头文件中的 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

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

提前致谢!

Part of a larger program I am making requires a path to be read in from the command line and stored in a class. Because paths can be an arbitrary size and it's needed in multiple functions, I store it in a char* in the header file. But, for some reason, when I assign a value to it, the program segfaults.

The debugger (gdb) shows the following:

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

Here's the program I wrote to demonstrate the problem:

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

I'm not sure why it crashes. Is there something wrong with the method I'm doing this? Also, rather than just switching to strings, I'd like to find out more about this problem.

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

苏别ゝ 2024-12-29 16:45:41

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

std::cin >> temp;

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

  • temp 设为 char[] 并且仅读取适合缓冲区的字符量。
  • temp 指向有效的缓冲区。
  • 更好,将 temp 设为 std::string,并让 std::string 类关心内存管理。

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

strcpy(filepath, temp);

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

temp (inside main) is uninitialized and not pointing to any valid allocated block of memory, therefore the line:

std::cin >> temp;

is causing input to be written into some unknown part of memory, causing undefined behaviour. You should either:

  • Make temp a char[] and only read in an amount of characters that will fit in the buffer.
  • Point temp to a valid buffer.
  • Better yet, make temp an std::string, and let the std::string class worry about the memory management.

You're also going to be having a similar problem with filePath after you fix the above problem. filePath is being set to NULL in the Test constructor, and then you're copying temp to the block of memory pointed by filePath in Test::set_path:

strcpy(filepath, temp);

NULL refers to an address that you're not allowed to dereference. You should change all of your C-strings to std::strings and use the std::string member functions and overloaded operators to deal with strings in C++.

捎一片雪花 2024-12-29 16:45:41

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

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

You call strcpy without allocating memory for the string to be copied in set_path. The manual page clearly states that dest must be large enough to contain the string in src. Besides you copy from an empty temporary. Although, your crash appears early, when you read from cin into an uninitialized pointer.

Use 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;
}

If you really preffer what you are doing:

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;
}

The second example is still broken. It is missing a proper destructor, copy constructor and assignment operator. I'll leave this as an exercise.

暮色兮凉城 2024-12-29 16:45:41
Test::Test() {
  filepath = NULL;
}

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

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

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

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

I'm not sure what you thought that strcpy was going to do, but what it does is copy from temp, which is uninitialized, to filepath, which is NULL. So neither parameter makes any sense.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文