开发者

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. 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).

So when you do sizeof, you're actually getting the size of an char *, not of the array.

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.

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. 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)

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


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).

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
  • 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)
  • The size of the array is SIZE, where SIZE has to be a constant.

If you are not sure what the template line is all about, that's probably out of scope for this discussion :-)

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜