-2

I have this code in c++ and I used vectors but I got this error:

error: Vector subscript out of range error.

Can some help me in this issue.

int const TN = 4;
vector <uint32_t> totalBytesReceived(TN);

void ReceivePacket(string context, Ptr <const Packet> p)
{
    totalBytesReceived[context.at(10)] += p->GetSize();
}

void CalculateThroughput()
{
    double mbs[TN];
    for (int f = 0; f<TN; f++)
    {
        // mbs = ((totalBytesReceived*8.0)/100000);
        mbs[f] = ((totalBytesReceived[f] * 8.0) / 100000);

        //totalBytesReceived =0;
        rdTrace << Simulator::Now().GetSeconds() << "\t" << mbs[f] << "\n";
        Simulator::Schedule(Seconds(0.1), &CalculateThroughput);
    }
}
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
user4871626
  • 31
  • 2
  • 10
  • What's your question? When do you actually allocate the vector? Did you resize it properly? – rlbond Jul 10 '15 at 20:36
  • 1
    This would be a good time to learn [how to use a debugger](http://ericlippert.com/2014/03/05/how-to-debug-small-programs/). – Captain Obvlious Jul 10 '15 at 20:37
  • my question is why I got this error ? here I defined the vector totalBytesReceived[context.at(10)] += p->GetSize(); – user4871626 Jul 10 '15 at 20:38
  • Because you're accessing an element that is _outside the bounds of the array_. – Captain Obvlious Jul 10 '15 at 20:38
  • 2
    What's that context string and is context.at(10) guaranteed to give a value between 0 and 3 inclusive? Note: Not '0', but the real 0. Using a string for that kind of data looks suspective to me. – Daniel Jour Jul 10 '15 at 20:41
  • 1
    Say character 10 in the `context` string is '2'. The character '2' in ASCII encoding (and I'm assuming ASCII here because it's the most likely encoding, but the problem holds for other encodings) is 50. So you won't be looking at `totalBytesReceived[2]`. You'll be looking at `totalBytesReceived[50]`. – user4581301 Jul 10 '15 at 20:54

2 Answers2

2

It seems like

totalBytesReceived[context.at(10)] += p->GetSize();

throws the exception because the char at position 10 of context is out of range. Since you use it to index the vector, it has to be in the range 0 to 3.

Looking at the content of context you posted:

"/NodeList/" 1 "/DeviceList/*/$ns3::WifiNetDevice/Mac/MacRx"
 ^         ^ ^
 0        10 12

If you want to extract the 1 and use it as an index, you need to use:

char c = context.at(12); // Extract the char.
int index = c - '0'; // Convert the character '1' to the integer 1.

This is because of the ASCII standard which determines how characters are stored as numbers.

Beta Carotin
  • 1,659
  • 1
  • 10
  • 27
0

Probably the real issue is that you get the character '1' and use its ASCII value as index to the vector instead of the intended integer value 1.

This out of bounds access is then undefined behaviour, which in your case leads to an exception.


The following is not the cause, leaving it for reference: The exception is probably coming from this expression:

context.at(10)

This is the only operation (*) involved that is actually performing bounds checking. The vector operator[] isn't doing that, neither does a C array check it's bounds.

So: Are you sure the string context is never shorter than 11 characters?

(*) Accessing a vector out of bounds is undefined behaviour, and throwing an exception is within the possible outcomes of that. Thanks to Beta Carotin and Benjamin Lindley for that.


This is the real thing:

Also note that a vector isn't resized like map when accessing an out of bounds index using operator[], so unless you can guarantee that the characters in the string are between 0 and 3 inclusive this will be your next issue.

And this means (size_t)0 and (size_t)3, not the characters '0' and '3'.

Daniel Jour
  • 15,896
  • 2
  • 36
  • 63
  • This is not universally true. Any implementation of `vector` may choose to perform bounds checking within `operator[]`. See [here](http://stackoverflow.com/questions/1290396/how-to-make-stdvectors-operator-compile-doing-bounds-checking-in-debug-but). – Beta Carotin Jul 10 '15 at 20:49
  • the string context is: "/NodeList/" 1 "/DeviceList/*/$ns3::WifiNetDevice/Mac/MacRx"; So I want to extract number "1". so surely its never less than 11 characters – user4871626 Jul 10 '15 at 20:52
  • @BetaCarotin I didn't know that, but isn't this strictly speaking a violation of the standard? – Daniel Jour Jul 10 '15 at 20:53
  • 1
    @DanielJour: No. Accessing out of bounds with `operator[]` is undefined behavior. Throwing an exception is certainly within the bounds of possible outcomes of undefined behavior. Many implementations do it in debug mode. – Benjamin Lindley Jul 10 '15 at 20:54
  • Do you want that 1? This is a char, so it will be a '1' which is not equal to 1. Is the string always long enough? – Daniel Jour Jul 10 '15 at 20:55
  • @BenjaminLindley Indeed, that makes sense. – Daniel Jour Jul 10 '15 at 21:00