c++ memory mess in arrays - c++

Why does this happen?
u_char macDst[6], macSrc[6], ipType[2]={0x88, 0x92};
u_char header[] = {0x04,0x00,0x20,0x00,...,};
const int len = sizeof(macDst) + sizeof(macSrc) + sizeof(header) + 2;
u_char* pck[len];
int j = 0, length = sizeof(macDst);
for (j; j < length; j++)
{
pck[j] = &macDst[j];
}
length += sizeof(macSrc);
for (j; j < length; j++)
{
pck[j] = &macSrc[j - sizeof(macDst)];
}
pck[j++] = &ipType[0];
pck[j++] = &ipType[1];
length += sizeof(header) + 2;
for (j; j < len; j++)
{
pck[j] = &header[j - sizeof(macDst) - sizeof(macSrc)];
}
u_char testSend[170];
memcpy(testSend, *pck, sizeof(pck));
The var testSend only has macDst values (before initialized), while in the pointer I have all of them. If I copy them one by one, I get a good result:
for (int k = 0; k < 170; k++)
{
testSend[k] = *pck[k];
}
Any idea??
Thanks!!
Edit:
This is a physic problem:
-----ooooooooo------------aaaa----bbbb----
- Null Data
When I make the pointers array I am doing this:
oooooooooaaaabbbb
But when I sent the packet and when I did the memcpy (or memmove) I was saying this: take this pointer and this amount of memory and copy them:
----|oooooooooo----------|----aaaaa----bbbb----
being the amount the sum of the 3 memory places.

I find the code convoluted, and I would never write it this way. Still, the error here:
memcpy(testSend, *pck, sizeof(pck));
You are dereferencing pck - and point to the first element, which is a char*. This is what you copy using your memcpy. On the other hand, your hand-written loop does dereference the pointer before copying it.

Fill the testSend array directly:
u_char *p = testSend;
memcpy(p, macDst, sizeof(macDst)); p += sizeof(macDst);
memcpy(p, macSrc, sizeof(macSrc)); p += sizeof(macSrc);
memcpy(p, ipType, sizeof(ipType); p += sizeof(ipType);
memcpy(p, header, sizeof(header));

Related

Memory allocation with looping in C++

I have a List class for char arrays. And I want to push back N arrays from 'a' to 'a..a'.
char* x;
SList list;
for (unsigned int i = 1; i < n+1; i++) {
x = new char[i+1];
for (unsigned int j = 0; j < i; j++) {
x[j] = 'a';
}
x[i] = '\0';
list.push_back(&x);
}
But every time, x has the same address. And in result, my List object contains N pointers to the same address.
Is there a way to push back these arrays in loop with correct memory allocation?
Before asking found this question, but it doesn't provide a cool solution for my problem.
In each iteration of the loop x = new char[i+1]; returns a different address, which is stored in x. So the value of x changes in each iteration, yet, the address of x doesn't.
Did you mean
list.push_back(x);
to add the address of the newly allocated memory? Of course this would require you to change the type of list the a collection of char *.
It must be mentioned that dereferencing &x after x goes out of scope will lead to undefined behaviour, because x doesn't exist anymore. You fill list with dangling pointers.
Finally I'd like to mention that you could avoid the nasty manual memory management and simply use a std::vector<std::string>.
std::vector<std::string> list;
for (unsigned int i = 1; i < n+1; i++) {
std::string newString(i, 'a'); // string with i times 'a'
list.push_back(newString);
}
Ok. I found a pretty straightforward solution:
char** x = new char*[n];
SList sl;
for (unsigned int i = 0; i < n; i++) {
x[i] = new char[i+1];
for (unsigned int j = 0; j < i; j++) {
x[i][j] = 'a';
}
x[i][i] = '\0';
sl.push_back(&x[i]);
}
With having N addresses to store pointers to arrays. I can just add their addresses to my list object

The array in my singleton isn't keeping information after leaving a function and then it crashes when it tries to access the information again

I have an array called int **grid that is set up in Amazon::initGrid() and is made to be a [16][16] grid with new. I set every array value to 0 and then set [2][2] to 32. Now when I leave initGrid() and come back in getGrid() it has lost its value and is now 0x0000.
I don't know what to try, the solution seems to be really simple, but I'm just not getting it. Somehow the data isn't being kept in g_amazon but I could post the code.
// Returns a pointer to grid
int** Amazon::getGridVal()
{
char buf[100];
sprintf_s(buf, "Hello %d\n", grid[2][2]);
return grid;
}
int Amazon::initGrid()
{
int** grid = 0;
grid = new int* [16];
for (int i = 0; i < 16; i++)
{
grid[i] = new int[16];
for (int j = 0; j < 16; j++)
{
grid[i][j] = 0;
}
}
grid[2][2] = 32;
return 0;
}
int **grid;
g_amazon = Amazon::getInstance();
g_amazon->initGrid();
grid = g_amazon->getGridVal();
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 16; j++)
{
int index;
index = (width * 4 * i) + (4 * j);
int gridval;
gridval = grid[i][j];
lpBits[index] = gridval;
lpBits[index + 1] = gridval;
lpBits[index + 2] = gridval;
}
}
It crashes when I run it at the line where sprintf_s prints out [2][2] and it also crashes when I get to gridval = grid[i][j] because it's at memory location 0x000000.
The variable
int** grid
in the initGrid() function is a local variable. Edit** When the function returns the variable is popped off the stack. However, since it was declared with the new operator the memory still exists on the heap; it is simply just not pointed to by your global grid variable.
#Dean said in comment:
I have grid as an int** grid; in class Amazon {}; so shouldn't it stay in memory or do I need a static var.
That is the problem:
local int **grid; on Amazon::initGrid::
is masking
member int **grid; on Amazon::
as the first context has higher priority in name lookup.
So initGrid() allocates memory referenced only by a local pointer. That pointer no longer exists when you return from this function, Amazon::grid was never touched on initialization and you're also left with some bad memory issues.
So, as commented by #Remy-Lebeau, I also suggest
Consider using std::vector> or std::array, 16> instead. There is no good reason to use new[] manually in this situation.

snprintf copying 2D char array

Trying to populate a 2D char array. This code should just work:
char FilenamesBuffer[3][64] = {{"test1"},{"test2"},{"test3"}};
char FilenamesBufferTest[3][64] = {{"unwritten1"},{"unwritten2"},{"unwritten3"}};
//print destination buffer before write
for (i = 0; i < 3; i++)
{
for (j = 0; j < 64; j++)
{
Serial.printf("%c", *((char*)FilenamesBufferTest+(i*64) + j));
}
Serial.println();
}
Serial.println();
//copying
for (i = 0; i < 3; i++)
{
Serial.print("copying ");Serial.println(i);
snprintf(*(FilenamesBufferTest+i*64), 64, "%s", *(FilenamesBuffer+i*64));
}
Serial.println();
//print destination buffer after write
for (i = 0; i < 3; i++)
{
for (j = 0; j < 64; j++)
{
Serial.printf("%c", *((char*)FilenamesBufferTest+(i*64) + j));
}
Serial.println();
}
Outputs:
unwritten1
unwritten2
unwritten3
copying 0
copying 1
copying 2
test1ten1
unwritten2
unwritten3
Looks like only the first row gets copied. I tried casting the char array addresses as (char**) which doesn't seem like it should make a difference. But it breaks the program.
snprintf(*((char**)FilenamesBufferTest+i*64), 64, "%s", *((char**)FilenamesBuffer+i*64));
Output:
unwritten1
unwritten2
unwritten3
copying 0
and then strangely
snprintf(((char*)FilenamesBufferTest+i*64), 64, "%s", ((char*)FilenamesBuffer+i*64));
works
You're confusing yourself by using pointer arithmetic to access arrays -- don't do it; use array accesses instead.
So when you do:
*(FilenamesBufferTest+i*64)
That's the same as FilenamesBufferTest[i*64] which is out-of-bounds when i is anything other than 0. You want FilenamesBufferTest[i], which would be:
*((char *)FilenamesBufferTest+i*64)
if you really want to do the explicit arithmetic, but that is much harder.

free up memory on a double pointer

//char char **p; declared in .h file
size_t bs = 5;
size_t Size = sizeof(obj);
p = (char**)malloc(bs);
for (size_t i = 0; i < bs;i++){p[i] = (char*)malloc(Size);}
for (size_t j = 0; j < bs-1; j ++){p[j] = &(p[j + 1][0]); }
for (size_t i = 0; i < bs; i++){free(p[i]);}
free(p);
my code stalls up when trying to free the last element of p in the for loop. Anyone what i might be doing wrong?
EDIT: I still have the same problem even when changing it to (char*)malloc(bs sizeof(char *));
this still does not work:
size_t bs = 5;
size_t Size = sizeof(obj);
p = (char**)malloc(bs* sizeof(char *));
for (size_t i = 0; i < bs;i++){p[i] = (char*)malloc(Size);}
for (size_t j = 0; j < bs-1; j ++){p[j] = &(p[j + 1][0]); }
for (size_t i = 0; i < bs; i++){free(p[i]);}
free(p);
using new instead of malloc does not solve the issue either
However this code frees up the memory fine.
size_t bs = 5;
size_t Size = sizeof(obj);
p = (char**)malloc(bs* sizeof(char *));
for (size_t i = 0; i < bs;i++){p[i] = (char*)malloc(Size);}
for (size_t i = 0; i < bs; i++){free(p[i]);}
free(p);
so the problem seem to be something with this piece of code
for(size_t j = 0; j < bs-1; j ++){p[j] = &(p[j + 1][0]); }
I want this to be an implicit linked list, anyone know have an idea what i am doing wrong?
You are not allocating enough space for the pointers. Change to
p = malloc(bs * sizeof(char*));
At the first malloc, you donĀ“t need 5 byte, but 5 times a pointer.
p = (char**)malloc(bs * sizeof(char *));
The problem is that you:
allocate an array of 5 pointers
allocate 5 arrays of characters and store them in that first array
move those pointers down in the array, overwriting (and losing) the first pointer and duplicating the last one
attempt to free the 5 pointers in the array.
So on this last step, you free a pointer twice (as the last two entries at p[3] and p[4] are the same), causing undefined behavior.
You say you want "an implicit linked list", implying that you're trying to stuff pointers into the objects (rather than into the top level array, as you are doing), in which case you want something like:
for(size_t j = 0; j < bs-1; j ++) { *(char **)p[j] = p[j + 1]); }
*(char **)p[bs-1] = 0; // null terminate the linked list
this assumes that obj is defined something like:
struct obj {
struct obj *next;
// more fields

Easiest way to repeat a sequence of bytes into a larger buffer in C++

Given (in C++)
char * byte_sequence;
size_t byte_sequence_length;
char * buffer;
size_t N;
Assuming byte_sequence and byte_sequence_length are initialized to some arbitrary length sequence of bytes (and its length), and buffer is initialized to point to N * byte_sequence_length bytes, what would be the easiest way to replicate the byte_sequence into buffer N times? Is there anything in STL/BOOST that already does something like this?
For example, if the sequence were "abcd", and N was 3, then buffer would end up containing "abcdabcdabcd".
I would probably just go with this:
for (int i=0; i < N; ++i)
memcpy(buffer + i * byte_sequence_length, byte_sequence, byte_sequence_length);
This assumes you are dealing with binary data and are keeping track of the length, not using '\0' termination.
If you want these to be c-strings you'll have to allocate an extra byte and add in the '\0' a the end. Given a c-string and an integer, you'd want to do it like this:
char *RepeatN(char *source, size_t n)
{
assert(n >= 0 && source != NULL);
size_t length = strlen(source) - 1;
char *buffer = new char[length*n + 1];
for (int i=0; i < n; ++i)
memcpy(buffer + i * length, source, length);
buffer[n * length] = '\0';
}
Repeating the buffer while avoiding pointer arithmetic:
You can use std::vector < char > or std::string to make things easier for you. Both of these containers can hold binary data too.
This solution has the nice properties that:
You don't need to worry about memory access violations
You don't need to worry about getting the size of your buffer correct
You can append sequences at any time to your buffer without manual re-allocations
.
//Note this works even for binary data.
void appendSequenceToMyBuffer(std::string &sBuffer
, const char *byte_sequence
, int byte_sequence_length
, int N)
{
for(int i = 0; i < N; ++i)
sBuffer.append(byte_sequence, byte_sequence_length);
}
//Note: buffer == sBuffer.c_str()
Alternate: For binary data using memcpy:
buffer = new char[byte_sequence_length*N];
for (int i=0; i < N; ++i)
memcpy(buffer+i*byte_sequence_length, byte_sequence, byte_sequence_length);
//...
delete[] buffer;
Alternate: For null terminated string data using strcpy:
buffer = new char[byte_sequence_length*N+1];
int byte_sequence_length = strlen(byte_sequence);
for (int i=0; i < N; ++i)
strcpy(buffer+i*byte_sequence_length, byte_sequence, byte_sequence_length);
//...
delete[] buffer;
Alternate: If you are filling the buffer with a single value:
buffer = new char[N];
memset(buffer, byte_value, N);
//...
delete[] buffer;
If N is known to be a power of 2, you can copy from the first part of your buffer to subsequent parts, increasing the amount copied each time:
assert((N > 0) && ((N & (N-1)) == 0));
memcpy(buffer, byte_sequence, byte_sequence_length);
for (size_t i = 1; i < N; i *= 2)
memcpy(buffer + i * byte_sequence_length, buffer, i * byte_sequence_length);
Edit: It is trivial to extend this to work when N is not a power of 2. Here's an improved version, which removes all constraints on N and also replaces the odd for statement with a while.
if (N > 0)
memcpy(buffer, byte_sequence, byte_sequence_length);
size_t copied = 1;
while (copied < N)
{
size_t tocopy = min(copied, N - copied);
memcpy(buffer + copied * byte_sequence_length, buffer, tocopy * byte_sequence_length);
copied += tocopy;
}
You can use the STL algorithm Generate:
MSDN: Generate