简体   繁体   English

试图避免分段错误,但我的输出看起来很奇怪(C ++)

[英]Trying to avoid segmentation fault, but my output looks weird (C++)

A homework project I'm working on uses static and dynamic arrays. 我正在做的家庭作业项目使用静态和动态数组。 However, I'm not implementing the dynamic arrays yet and this is a weird discrepancy trying to get the length of my static arrays. 但是,我还没有实现动态数组,这是一个奇怪的差异,试图获得我的静态数组的长度。

I used a series of cout statements to try and find out what was giving me a segmentation fault, since the process seemed straightforward. 我使用了一系列cout语句来尝试找出导致分段错误的原因,因为这个过程看起来很简单。 What I found was that in my driver, it was computeing a correct range and length, but once I passed the array into a user-defined class function, the same statements performed on the same array had different results. 我发现在我的驱动程序中,它计算的是正确的范围和长度,但是一旦我将数组传递给用户定义的类函数,在同一个数组上执行的相同语句就会产生不同的结果。

My driver function: 我的驱动功能:

using namespace std;

#include <iostream>
#include "/user/cse232/Projects/project07.string.h"

int main()
{
  const char string1[] = {'a', 'b', 'c', 'd', 'e', 'f'};
  String test1();
  cout << "Size of array: " << sizeof(string1) << endl;
  cout << "Size of item in array: " << sizeof(char) << endl;
  cout << "Length of array: " << (sizeof(string1)/sizeof(char)) << endl;
  cout << "Range of array" << (sizeof(string1)/sizeof(char))-1 << endl << endl;

  String test2(string1);
}

When run, I get this output from the driver: 运行时,我从驱动程序获取此输出:

Size of array: 6
Size of item in array: 1
Length of array: 6
Range of array5

My support file: 我的支持文件:

/* Implementation file for type "String" */

using namespace std;

#include <iostream>
#include "/user/cse232/Projects/project07.string.h"

String::String( const char Input[] )
{

  cout << "Size of array: " << sizeof(Input) << endl;
  cout << "Size of item in array: " << sizeof(char) << endl;
  cout << "Length of array: " << (sizeof(Input)/sizeof(char)) << endl;
  cout << "Range of array" << (sizeof(Input)/sizeof(char))-1 << endl << endl;

/*  Bunch of reallocation stuff that is commented out 
for the time being, unimportant*/
}

String::~String()
{
  Capacity = 0;
  Length = 0;
  Mem = NULL;
}

And here is the output I get from the support file, 这是我从支持文件中获得的输出,

Size of array: 4
Size of item in array: 1
Length of array: 4
Range of array3

which is obviously not right. 这显然是不对的。 If it helps, here is the header file (omitting unimplemented functions). 如果有帮助,这里是头文件(省略未实现的功能)。 It is unalterable: 这是不可改变的:

/******************************************************************************
   Project #7 -- Interface file for type "String"
******************************************************************************/

#ifndef STRING_
#define STRING_

using namespace std;

#include <iostream>

class String
{
  private:

    unsigned Capacity;  // Number of memory locations reserved
    unsigned Length;    // Number of memory locations in use
    char * Mem;         // Pointer to memory to hold characters

  public:

    // Construct empty string
    //
    String()
    {
      Capacity = 0;
      Length = 0;
      Mem = NULL;
    }

    // Destroy string
    //
    ~String();

    // Construct string by copying existing string
    //
    String( const String& );

    // Construct string by copying C-style character string
    //
    String( const char[] );

#endif

My biggest question is why I am getting two separate outputs. 我最大的问题是为什么我得到两个单独的输出。 The first one is the one I need to use while allocating memory; 第一个是我在分配内存时需要使用的那个; otherwise I get a segmentation fault. 否则我会遇到分段错误。 Can anyone offer advice? 有人可以提供建议吗?

Your function is actually doing something you don't realize - it decays the array you pass into a pointer to the first element. 你的函数实际上正在做一些你没有意识到的事情 - 它会将你传入的数组衰减到指向第一个元素的指针。

Basically your function signature: String::String( const char Input[] ) would be equivalent to the signature String::String(const char *input) . 基本上你的函数签名: String::String( const char Input[] )等价于签名String::String(const char *input)

So when you do sizeof , you're actually getting the size of an char * , not of the array. 所以当你做sizeof ,你实际上得到的是char *的大小,而不是数组的大小。

You cannot pass an array directly to the function and expect to be able to get the size of the array. 您不能将数组直接传递给函数,并期望能够获得数组的大小。 If you must use raw arrays like this, you can alter your function so that you pass in the size of the array with it. 如果必须使用这样的原始数组,则可以更改函数,以便使用它传递数组的大小。 If you can not modify the signature, then another thing you can do is put in a sentinel value (like \\0 byte) and use a loop to count the size of the array. 如果你不能修改签名,那么你可以做的另一件事就是放入一个sentinel值(比如\\0字节)并使用一个循环来计算数组的大小。

edit 编辑

What I think you really want to learn about is C-style strings , rather than just using a character array that is not null-terminated. 我认为你真正想要了解的是C风格的字符串 ,而不仅仅是使用非空终止的字符数组。 This does fit the model of what your assignment seems to want you to do, and allows you to avoid manipulating these immutable headers. 这确实符合您的任务似乎要求您执行的操作的模型,并允许您避免操作这些不可变的标头。

once you pass an array into a function the compiler no longer knows its size 一旦将数组传递给函数,编译器就不再知道它的大小

the called function just sees 被调用的函数只是看到了

foo(char[])

It does not know how big it is, the array has become a pointer and when you ask for the size of a pointer you get 4 (on a 32 bit machine) 它不知道它有多大,数组已成为一个指针,当你要求指针大小时,你得到4(在32位机器上)

The in memory representation of an array does not contain its length. 数组的内存表示不包含其长度。 This is a well known and intractable problem, its why std::vector exists 这是一个众所周知且难以处理的问题,它为什么std :: vector存在

Unfortunately you cannot pass arrays like this. 不幸的是你无法传递这样的数组。 When you have a function like this: 当你有这样的功能:

String::String( const char Input[] )

you are only passing in a pointer to the very first element. 你只是传递指向第一个元素的指针。 You will also need to pass the size of the array into the constructor. 您还需要将数组的大小传递给构造函数。

Others have answered your question, so I'll just supplement it with a little idea - There is a way you can pass an array to a function without having it decay into a pointer. 其他人已经回答了你的问题,所以我就用一点点想法补充进去- 你可以传递一个数组的功能,而无需其衰变成一个指针的方式。

const size_t SIZE = 6; //Or whatever other array size you want to pass. 
String::String(const char (&Input)[SIZE])
{
    //TODO
}

Since it's not easy to always count the size of your array, a better mechanism looks like this - 由于总是计算数组大小并不容易,因此更好的机制看起来像这样 -

template<size_t N>
String::String(const char (&Input)[N])
{
    //TODO
}

If you don't know what size_t means, just assume that it is similar to int for now, and you'll learn more about this eventually (either by teaching yourself, or in some textbook. Probably the former). 如果你不知道size_t是什么意思,那么现在就假设它与int类似,你最终会更多地了解它(通过教自己,或者在一些教科书中。可能是前者)。

The somewhat weird looking parameter to the function - 函数有点奇怪的参数 -

const char (&Input)[SIZE]

means that you are passing 意味着你正在经过

  • A reference (denoted by &) 参考(用&表示)
  • It's called Input 它叫做Input
  • It's a reference to an array made up of const char 's (Note: If I had put the & outside the parenthesis, like this: const char & Input[SIZE] , then it would be treated as an array of const char& 's - thus the need to introduce parenthesis to make sure that the reference is to the array itself, not each element in th3e array) 它是对由const char组成的数组的引用(注意:如果我把括号括在&括号之外,就像这样: const char & Input[SIZE] ,那么它将被视为const char&的数组) - 因此需要引入括号以确保引用是数组本身,而不是引入数组中的每个元素)
  • The size of the array is SIZE , where SIZE has to be a constant. 数组的大小是SIZE ,其中SIZE必须是常量。

If you are not sure what the template line is all about, that's probably out of scope for this discussion :-) 如果您不确定template行的全部内容,那可能超出了本次讨论的范围:-)

All of this will only work for true arrays, for which the size is a constant value that can be computed at compile-time. 所有这些只适用于真正的数组,其大小是一个可以在编译时计算的常量值。 Otherwise, it's not going to work, and you'll have to use a sentinel value (like '\\0' and dynamically compute the length of your 'array' by looping over the contents. 否则,它不会起作用,你将不得不使用一个sentinel值(比如'\\0'并通过循环遍历内容来动态计算'数组'的长度。

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

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