-3

The following question concerns the use of a vector and memcpy. Vector functions being used are, .push_back, .data(), .size().

Information about the msg.

a)

#define BUFFERSIZE 8<<20
char* msg = new char[(BUFFERSIZE / 4)];

Question: Why doesn't code block b) work?

When I run the code below, using vector.push_back in a for loop, it causes the software I'm working with to stop working. I'm not sending the "msg" nor am I reading it, I'm just creating it.

b)

mVertex vertex;
vector<mVertex>mVertices;
for (int i = 0; i < 35; i++)
{
vertex.posX = 2.0;
vertex.posY = 2.0;
vertex.posZ = 2.0;
vertex.norX = 2.0;
vertex.norY = 2.0;
vertex.norZ = 2.0;
vertex.U = 0.5;
vertex.V = 0.5;
mVertices.push_back(vertex);
}
memcpy(msg,                                     // destination
    mVertices.data(),                           //  content  
    (mVertices.size() * sizeof(mVertex)));      // size

Screenshot of the error message from the software

By adding +1 to mVertices.size() at the very last row, the software works fine. See the example code below.

c)

mVertex vertex;
vector<mVertex>mVertices;
for (int i = 0; i < 35; i++)
{
vertex.posX = 2.0;
vertex.posY = 2.0;
vertex.posZ = 2.0;
vertex.norX = 2.0;
vertex.norY = 2.0;
vertex.norZ = 2.0;
vertex.U = 0.5;
vertex.V = 0.5;
mVertices.push_back(vertex);
}
memcpy(msg,                                     // destination
    mVertices.data(),                           //  content  
    (mVertices.size()+1 * sizeof(mVertex)));    // size

The code also work, if I remove the for loop.

d)

mVertex vertex;
vector<mVertex>mVertices;

vertex.posX = 2.0;
vertex.posY = 2.0;
vertex.posZ = 2.0;
vertex.norX = 2.0;
vertex.norY = 2.0;
vertex.norZ = 2.0;
vertex.U = 0.5;
vertex.V = 0.5;
mVertices.push_back(vertex);

memcpy(msg,                                     // destination
    mVertices.data(),                           //  content  
    (mVertices.size() * sizeof(mVertex)));      // size
Jesper
  • 11
  • 1

2 Answers2

1

The problem is a basic macro issue: macros define text replacements, not logical or arithmetic expressions.

#define BUFFERSIZE 8<<20

creates a text macro. When you use it in this expression (I've removed the redundant parentheses):

char* msg = new char[BUFFERSIZE / 4];

the preprocessor replaces BUFFERSIZE with 8 << 20, so it's as if you had written

char* msg = new char[8 << 20 / 4];

and the problem is that 8 << 20 / 4 is 256. That's because the expression is evaluated as 8 << (20/4), where presumably you intended it to be (8 << 20) / 4. To fix that (and you should always do this with macros), put parentheses around the expression in the macro itself:

#define BUFFERSIZE (8<<20)

Incidentally, that's why using a named variable (whether constexpr or otherwise) makes the problem go away: the variable gets the value 8 << 20, not the text, so all is good.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • Very well explained answer. This was exactly the problem. Now my code is running smoothly again :) – Jesper Jun 14 '18 at 13:15
0

The define doesn't do what you think.

#define BUFFERSIZE 8<<20

yields BUFFERSIZE / 4 == 8 << 20 / 4 == 8 << 5 == 256. So the allocated memory in msg is to small to hold mVertices and

memcpy(msg, mVertices.data(), (mVertices.size() * sizeof(mVertex)));

writes into wrong memory. This can produce runtime errors.

You should use constexpr instead of define to avoid such problems.

Thomas Sablik
  • 16,127
  • 7
  • 34
  • 62
  • How does that yield 820 ? – M.M Jun 14 '18 at 08:11
  • How many bytes are 8<<20? 2^20 = 1,048,576 bits 8 * 1,048,576 bits = 8,388,608 bits 1 bit is 0.125 bytes. 8,388,608 bits * 0.125 = 1,048,576 bytes Buffersize = 1,048,576 bytes = ish 1048 MB – Jesper Jun 14 '18 at 08:42
  • @Jesper Size of your buffer is 8<<20 / 4 = 8<<5 = 256. Add parenthesis for correct value: (8<<20) / 4 – VLL Jun 14 '18 at 08:53