繁体   English   中英

分段故障。 是因为指针错误?

[英]Segmentation Fault. Is it because of bad pointer?

为什么会出现此细分错误(核心转储)? 最初告诉我这是因为我的指针p_p_tictactoe = new char * [cols],但是告诉我的是不对的。每组代码的目的在整个代码中都有注释。 代码正在运行,但是我得到了这个结果。 我知道for循环必须是主要问题。

Please enter a number of rows: 4
Please enter number of columns: 3
Enter a single character for position( << i << ): a  
Enter a single character for position( << j << ): b  
Segmentation fault (core dumped)



 #include <iostream>

        using namespace std;

        int main()
        {
           // TODO:  Below each Bp_tictactoe` of type pointer-to-a-pointer-to-a-char
       char **p_p_tictactoe;


       // 2. Prompt your user to enter a number of rows, then a number of columns.
       //    store their answers in the variables `rows` and `cols`.
       char rows;
       char cols;
       cout << "Please enter a number of rows: ";
       cin >> rows;
       cout << "Please enter number of columns: ";
       cin >> cols;
       // 3. Allocate a 1-dimensional array of pointers-to-chars (length == `rows`)
       //    and store its address in `p_p_tictactoe`
       p_p_tictactoe = new char*[rows];
       // 4. Use a for-loop to allocate a dynamic array of chars (length == `cols`)
       //    for i from 0 to rows - 1 and store its address in `p_p_tictactoe[i]`.
       for (int i = 0; i < rows - 1; i++)
       {
         p_p_tictactoe = new char*[cols];
       }
       // 5. Use a for-loop to prompt the user to enter a char for each position in
       //    (" << i << ", " << j << "): "
       //    As you read each char, store it in the array.
       // 6. Use a nested for-loop to print the array, one row per line.  The chars
       //    for each row should be space-separated.  For example, if the array is
       //    2 x 3 and stores the values A, B, C, X, !, &, the output should look
       //    like:
       //       A B C
       //       X ! &\


       char new_input1;
       char new_input2;
       for (int i = 0; i < rows; i++)
       {
          for (int j = 0; j < cols; j++)
          {
             cout << "Enter a single character for position( << i << ): ";
             cin >> new_input1;
             cout << "Enter a single character for position( << j << ): ";
             cin >> new_input2;
             *p_p_tictactoe[i] = new_input1;
             *p_p_tictactoe[j] = new_input2;
             cout << *p_p_tictactoe[i] <<endl;
          }  
       }
       // *** Prevent memory leaks by deallocating dynamic memory when you are done
       // using it. ***

       // 7. Use a for-loop to delete each row of the dynamic array.                


       // 8. Delete the pointer-to-a-pointer to release the array of row pointers,
       //    and set its value to NULL to avoid accessing invalid memory.
for (int i = 0; i < 3; i++)
{
delete[] p_p_tictactoe[i];
delete[] p_p_tictactoe;
}
cout << "Bye!" << endl;
return 0;
    }

除其他外,您对p_p_tictactoe的分配不正确。 这是一个双指针,仅表示它是指向指针数组的指针。 您的两步分配是正确的想法,但是您在for循环中所拥有的是不正确的。 p_p_tictactoe = new char*[rows] ,您现在有了一个指向char*类型数组的指针。 因此,如果rows为4,则您现在的内存如下所示:

 p_p_tictactoe[0] == char* --> junk
              [1] == char* --> junk
              [2] == char* --> junk
              [3] == char* --> junk

您现在必须遍历这4个char*每一个并为其分配空间。 每个char*必须指向chars数组。 这是注释为您提供有关遍历和使用p_p_tictactoe[i]索引的提示的p_p_tictactoe[i]

 for (int i = 0; i < rows - 1; i++)
 {
   p_p_tictactoe[i] = new char[cols];
 }

现在,对于cols == 3 ,在内存中有:

 p_p_tictactoe[0] == char* --> 3 consecutive bytes
              [1] == char* --> 3 consecutive bytes
              [2] == char* --> 3 consecutive bytes
              [3] == char* --> 3 consecutive bytes

您发布的代码是内存泄漏。 每次执行p_p_tictactoe = new char*[#] ,操作系统都会进入堆以获取足够的内存用于分配。 您不必跟踪先前的指针,也不先释放它,因此分配的内存现在没有指向它的指针。

同样的理论也适用于释放内存。 最后您拥有的不是很正确。 解除分配始终是分配的镜像。 显然,这是一项家庭作业,因此我不会发布该代码,但是除了反向之外,它与分配相同。

我强烈建议使用gdb ,它是linux的文本调试器(或任何等效的调试器)。 如果您希望成功使用C / C ++进行编码,则必须学习内存在堆栈和堆上的工作方式,并且必须学习如何正确地对其进行管理,否则您将遭受重创。 gdb起初有点令人生畏,但是它可以让您打印出内存地址并检查内存,这对于学习和重新执行您认为的内容非常有帮助。

我认为这里的问题是,您应该为双指针变量采用一个双精度数组..您将两个不同的东西重新分配给一个变量..

代码的一个问题是您的宽度和高度没有按照您认为的方式被解释。 当您编写此代码时:

char width;
cin >> width;

...结果程序读取一个字符,并将其ASCII值分配给width 因此,如果输入“ 4”,则width == 52值为true ,而width == 4 false (但是width == '4'true因为'4' == 52 )。

这个问题很容易解决:只需使用int代替char 无论如何,您不会节省任何内存,因为new可能正在创建字对齐的指针。

这是Tarang Gupta指出的问题的补充。

这是因为行:

*p_p_tictactoe[i] = new_input1;
*p_p_tictactoe[j] = new_input2;

您将其视为2维数组。

以下内容写错了:

 p_p_tictactoe = new char*[rows];
 for (int i = 0; i < rows - 1; i++)
   {
     p_p_tictactoe = new char*[cols];
   }

首先,您为p_p_tictactoe分配了一个大小为sizeof (char*[rows])并将其内容替换p_p_tictactoe = new char*[cols]; (int)row时间。 您的代码中有很多未使用和未引用的内存。

即使在更改代码以防止此错误之后,以下操作仍会引起问题:

for (int i = 0; i < 3; i++)
{
    delete[] p_p_tictactoe[i];
    delete[] p_p_tictactoe;
}

您将p_p_tictactoe 3次删除p_p_tictactoe分配和引用的空间。 它应该已经超出循环范围。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM