当动态c字符串'textString'被类成员函数显示时,导致分段错误11。

#include "Text.h"
#include <iostream>
#include <cstring>
using namespace std;

Text::Text(const char* textArray)
    {
      textLength = strlen(textArray);
      char* textString = new char[textLength];
      strcpy(textString, textArray);
      cout << textString << endl;
    }

Text::~Text()
{
  delete[] textString;
}

void Text::displayText() const
{
  cout << textString << endl;
}


我提供的驱动程序:

#include <iostream>
#include "Text.h"

using namespace std;

int main()
{
    Text *myString1;
    char tvshow[1000];

    cout << "\n\nWhat is the most recent TV show you watched?\n";
        cin.getline(tvshow, 1000);
        myString1 = new Text(tvshow);

    cout << "\n\nTV SHOW:\t";
        myString1->displayText();
        cout << "\t# CHARACTERS:\t" << myString1->getLength() << endl;

    return 0;
}


在Text类的构造方法中,行cout << textString << endl;按预期工作。但是,当主函数调用myString1->displayText();时,bash会以分段错误结束程序:11。

任何帮助将不胜感激。谢谢。

最佳答案

除了what Algirdas says之外,您的另一个问题是,您实际上没有分配类成员textString(假设您有一个成员),而是将其隐藏在构造函数中。
将构造函数更改为以下形式:

Text::Text(const char* textArray)
{
    textLength = strlen(textArray);
    textString = new char[textLength + 1];
    strcpy(textString, textArray);
    cout << textString << endl;
}


注意textString前面缺少的char *

我是怎么发现的?

与其他任何段错误一样,您应该学习如何调试。最好的工具是gdbvalgrind。用valgrind运行它可以给我:

$ echo franz | valgrind ./a.out
==6222== Memcheck, a memory error detector
==6222== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6222== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==6222== Command: ./a.out
==6222==


What is the most recent TV show you watched?
franz


TV SHOW:    ==6222== Invalid read of size 1
==6222==    at 0x4C32CF2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6222==    by 0x108DB6: Text::getLength() const (a.cpp:37)
==6222==    by 0x108E70: main (a.cpp:51)
==6222==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==6222==
==6222==
==6222== Process terminating with default action of signal 11 (SIGSEGV)
==6222==  Access not within mapped region at address 0x0
==6222==    at 0x4C32CF2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6222==    by 0x108DB6: Text::getLength() const (a.cpp:37)
==6222==    by 0x108E70: main (a.cpp:51)
==6222==  If you believe this happened as a result of a stack
==6222==  overflow in your program's main thread (unlikely but
==6222==  possible), you can try to increase the size of the
==6222==  main thread stack using the --main-stacksize= flag.
==6222==  The main thread stack size used in this run was 8388608.
==6222==
==6222== HEAP SUMMARY:
==6222==     in use at exit: 14 bytes in 2 blocks
==6222==   total heap usage: 5 allocs, 3 frees, 77,838 bytes allocated
==6222==
==6222== LEAK SUMMARY:
==6222==    definitely lost: 6 bytes in 1 blocks
==6222==    indirectly lost: 0 bytes in 0 blocks
==6222==      possibly lost: 0 bytes in 0 blocks
==6222==    still reachable: 8 bytes in 1 blocks
==6222==         suppressed: 0 bytes in 0 blocks
==6222== Rerun with --leak-check=full to see details of leaked memory
==6222==
==6222== For counts of detected and suppressed errors, rerun with: -v
==6222== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
fish: Process 6222, “valgrind” “echo franz | valgrind ./a.out” terminated by signal SIGSEGV (Address boundary error)


您可以清楚地看到,崩溃发生在getLength中,因为它试图访问地址0x0。当使用gdb运行它时,您将恰好在该位置停止并看到print textString,它为0,并且未正确初始化。

请阅读What is a debugger and how can it help me diagnose problems?以获取更多信息!

10-07 22:34